電腦安全-L10
Buffer Overflow Definition
- known as a
buffer overrunorbuffer overwrite - A condition at an interface under which
more input can be placed into a buffer or data holding area than the capacity allocated, overwriting other information. Attackers exploit such a condition to crash a system or to insert specially crafted code that allows them to gain control of the system.
Buffer overflow basics
- Programming error
- process 試圖
將資料儲存到超過限制大小的 buffer 之外的位置 - 覆寫相鄰的記憶體位置 (可能存放其他程式的變數與參數)
- process 試圖
- Buffer 可能在 process 的 stack, heap, data section
- 後果:
- 程式資料被破壞
- 非預期的控制權轉移
- 記憶體存取違規
- 執行由攻擊者選擇的程式碼
Example
- str2 覆寫到 str1 的記憶體位置,導致比對錯誤
Attacker
- Needs for the Attacker: 利用 Buffer Overflow
- 在某個程式中識別出一個 buffer overflow 的漏洞
- 可以
透過外部來源的資料觸發,而這些資料是由攻擊者所控制的
- 可以
- 了解該 buffer 在 process memory 中是如何被儲存的
- 以及其破壞相鄰記憶體位置的可能性
- 可能改變程式的執行流程
如何辨識具有漏洞的程式:
- 檢查程式原始碼
- 追蹤程式在處理超大輸入時的執行過程
- 使用工具自動辨識可能存在漏洞的程式
fuzzing: 一種軟體測試技術- 使用隨機產生的資料作為程式輸入
- 輸入的範圍可以非常大
- 用來測試程式是否能正確處理所有這些異常輸入
Programs
Basic machine level
- 所有由機器指令所操作的資料,都儲存在處理器 registers 或記憶體中
- 資料的解釋方式: 完全由指令的功能所決定
- 可以被視為整數值、資料的位址、字元陣列等
- 組合語言程式設計師的責任: 確保任何儲存的資料值都被正確地解讀
Assembly language programs
- 擁有對系統資源最大的存取權限
- 但也需要最高的開發成本與程式設計責任
Modern high-level programming languages
ex: Java, Python
- 具有強型別與合法操作的概念
- 不容易受到 buffer overflow 攻擊: flexibility and safety
- 不允許儲存超出限制的資料
- 代價是資源使用增加 (在編譯期與執行期都會加入檢查)
- 限制了程式撰寫的靈活性
Between these two extremes
ex: C and related languages
- 具有許多現代高階語言的控制結構與資料型別抽象
- 但仍允許直接存取低階系統資源
- 容易受到 buffer overflow 攻擊
- 存在大量歷史悠久、被廣泛使用但不安全,因此容易有漏洞的程式碼
Stack overflows
- 也被稱為
stack smashing - 當被攻擊的 buffer 位於
stack上時所發生的情況 - Stack frame 儲存的資料:
- Return address to the calling function (
Old frame pointer) Parameterspassed to the called function- Values of
local variables
- Return address to the calling function (
Example
- 覆寫到
Return address和Old frame pointer
More Vulnerabilities
- Potential for a buffer overflow: 存在於任何將資料複製 (copied) 或合併 (merged) 到 buffer 的地方
- 當程式沒有檢查以確認 buffer 是否足夠大,或被複製的資料是否被正確結束時,就會發生
- 有些資料是從程式外部讀入的
- 同一個程式內不同函數之間的不安全資料複製
- 常見的不安全 C 標準函式庫函數:
- 若未檢查正在傳輸資料的總大小,就不應該使用
- gets, sprintf, strcat, strcpy, vsprintf
Shellcode
- 由攻擊者提供的程式碼
- 通常儲存在 overflow 的 buffer 中
- 傳統上會將控制權轉移到使用者的
shell(命令列直譯器)
- 本質上就是
machine code(機器碼)- 與特定的處理器架構與作業系統相關
- 傳統上需要良好的組合語言能力才能撰寫
- 已經有許多網站與工具被開發出來,用以自動化這個過程
Example
某個入侵者已經以 normal user 的身分取得某系統的存取權限,並希望利用一個受信任工具中的 buffer overflow 漏洞,以取得更高的權限
- 使用 debugger 執行程式,分析以確定相關資訊
- 被攻擊目標 buffer 在 stack 上可能的位置
- 需要多少資料才能到達並覆蓋
old frame pointer與return address
- 假設已取得以下資訊
- How many bytes are needed to fill the buffer and reach the saved frame pointer?
Defending against buffer overflows
Compile-time defenses
強化新開發的程式,使其能抵抗攻擊
Choice of programming languages
- 使用
現代的高階程式語言 - 優點: 不容易受到 buffer overflow 攻擊
- 具有強型別概念以及允許的操作限制
- 編譯器會加入額外程式碼,以強制執行範圍檢查與合法操作
- 缺點:
- 必須在執行時額外執行檢查程式碼
- 彈性與安全性需要以
資源使用成本作為代價- 由於處理器效能快速提升,這種成本變得不那麼重要
- 會失去對某些低階指令與硬體資源的存取能力
Safe coding techniques
- C 語言的設計者更重視空間效率與效能,而不是型別安全性
- 假設程式設計師在撰寫程式時會謹慎行事
- 程式設計師需要檢查程式碼,並重寫任何不安全的寫法
- 程式碼不僅是為了正常且成功的執行
- 而是要持續意識到
事情可能會如何出錯 Graceful failure: 當發生意料之外的情況時,總是能做出合理的處理
- 而是要持續意識到
Language extensions and use of safe libraries
- 處理
dynamically allocated memory時會有更大的問題- 因為在編譯時無法得知記憶體大小資訊
- 需要語言擴充與函式庫 (library routines) 的支援
- 缺點:
- 通常會有效能上的損失
- 程式與函式庫需要使用修改過的編譯器重新編譯
- 對新的作業系統可行,但對第三方應用程式可能會造成問題
- 缺點:
- C 語言的常見問題: 使用不安全的標準函式庫函數
- 以較安全的替代版本取代它們
- ex:
Libsafe- 加入額外檢查,確保複製操作不會超出 stack frame 的範圍
- 動態函式庫: 不需要重新編譯現有程式
Stack protection mechanisms
- 在函式進入與離開時加入額外程式碼,用來
檢查 stack 是否有被破壞Stackguard: 最知名的保護機制之一,是一種 GCC 編譯器擴充- Function entry code: 在
old frame pointer位址下方寫入一個canary value(金絲雀值) - Function exit code: 檢查
canary value是否改變 canary value: 不可預測且在不同系統上不同- 避免被一起覆蓋成偽造數值
- 缺點:
- 所有需要保護的程式都必須重新編譯
- stack frame 結構被改變: 會造成一些程式 (例如 debugger) 出現問題
- 其他變種:
Stackshield與Return Address Defender (RAD)- 也是 GCC 擴充: 加入額外的函式進入與離開檢查程式碼
- 不會改變 stack frame 的結構
- Function entry code: 將 return address 複製到一個安全的記憶體區域
- Function exit code: 檢查 stack frame 中的 return address 是否與安全區域中的備份一致
- 與未修改的 debugger 相容
- 不會改變 stack frame 的結構
- 程式必須重新編譯
Run-time defenses
在現有程式執行時偵測並中止攻擊
- 可以透過 OS updates 來部署,以提供保護
- 通常需要重新編譯現有程式
- 通常會涉及記憶體管理機制的改變
Executable Address Space Protection
阻止在 stack 上執行程式碼- 將 virtual memory 的 pages 標記為不可執行 (
nonexecutable)- 需要記憶體管理單元 (MMU) 的支援
- 已成為現代作業系統的標準功能
- 缺點:
- 無法支援需要在 stack 上執行程式碼的情況
- ex: Java Runtime system, nested functions in C, Linux signal handlers
Address space randomization
- 改變關鍵資料結構的位置
Stack, heap, global data- 對每個 process 使用
random shift - 現代系統的位址空間很大: 浪費一部分空間的影響可以忽略不計
- 隨機化 heap buffer 的位置
- 標準函式庫函數的位置也會隨機化
Guard pages
- 在記憶體中的關鍵區域之間放置
guard pages- 在記憶體管理單元 (MMU) 中被標記為非法位址
- 任何對這些位址的存取都會導致 process 中止
- 擴展: 在 stack frames 與 heap buffers 之間也放置 guard pages
Other forms of overflow attacks
- Replacement stack frame
- Return to system call
- Heap overflows
- Global data area overflows
- Other types of overflows
Heap Overflow
- 攻擊的 buffer 位於
heap- 通常位於 program code 之上
- 記憶體是由程式動態請求,用於動態資料結構
- ex: linked lists
沒有 return address- 沒有簡單的方法可以進行控制流轉移
- 但可能存在可以被利用的
function pointer - 或者操控記憶體管理相關的資料結構
- Defenses:
- 讓 heap 變成不可執行 (
non-executable) - 隨機化 heap 上的記憶體配置方式
- 讓 heap 變成不可執行 (
next = malloc(sizeof(chunk_t));在 heap
Global Data Overflow
- 攻擊的 buffer 位於
global data- 可能位於 program code 之上
- 如果該區域同時包含 function pointer 與易受攻擊的 buffer
- 或者鄰近
process management tables - 目標是
覆蓋 function pointer,使其在之後被呼叫時執行攻擊者指定的程式碼
- Defenses:
- 將 global data region 設為不可執行,或隨機化其位置
- 移動 function pointers,或使用 guard pages
struct chunk {...} chunk;屬於 global data





