介紹
緩衝區是專門用於存放數據的記憶體區域,通常在將程式從一個程式段移動到另一個程式段時,或者在程式之間移動。緩衝區溢出通常可能由格式錯誤的輸入觸發;如果假設所有輸入都小於某個大小並且緩衝區被創建為該大小,那么產生更多數據的異常事務可能導致它寫入緩衝區的末尾。如果這會覆蓋相鄰的數據或可執行代碼,則可能導致程式行為不穩定,包括記憶體訪問錯誤,錯誤結果和崩潰。
利用緩衝區溢出的行為是眾所周知的安全漏洞。在許多系統中,程式的記憶體布局或整個系統都是明確定義的。通過傳送旨在引起緩衝區溢出的數據,可以寫入已知可保存可執行代碼的區域並將其替換為惡意代碼,或者有選擇地覆蓋與程式狀態有關的數據,從而導致未被原始程式設計師。緩衝區在作業系統(OS)代碼中很常見,因此可以進行執行許可權提升的攻擊並獲得對計算機資源的無限制訪問。 1988年著名的莫里斯蠕蟲將其作為攻擊技術之一。
通常與緩衝區溢出相關的程式語言包括C和C ++,它們不提供內置保護以防止訪問或覆蓋記憶體的任何部分中的數據,也不會自動檢查寫入數組的數據(內置緩衝區類型)是否在該數組的邊界。邊界檢查可以防止緩衝區溢出,但需要額外的代碼和處理時間。現代作業系統使用各種技術來對抗惡意緩衝區溢出,特別是通過隨機化記憶體布局,或故意在緩衝區之間留出空間並尋找寫入這些區域(“金絲雀”)的動作 。
歷史
早在1972年,計算機安全技術規劃研究就提出了這樣一項技術:“執行此功能的代碼不會正確檢查源地址和目標地址,允許部分監視器覆蓋,因此緩衝區溢出被理解並部分公開記錄。用戶。這可以用來將代碼注入監視器,允許用戶控制機器。“ 。顯示器將被稱為核心。
最早記錄的對緩衝區溢出的惡意攻擊是在1988年。它是Morris蠕蟲在網際網路上傳播自身的幾個漏洞之一。該程式被利用是Unix上的一項名為finger的服務。後來,在1995年,Thomas Lopatic獨立地重新發現了緩衝區溢出,並在Bugtraq安全郵件列表上公布了他的發現。一年後,1996年,Elias Levy(也稱為Aleph One)在Phrack雜誌上發表了題為“Smashing the Stack for Fun and Profit”的文章,逐步介紹了利用基於堆疊的緩衝區溢出漏洞。
從那時起,至少有兩個主要的網際網路蠕蟲利用緩衝區溢出來破壞大量系統。 2001年,Code Red蠕蟲在微軟的Internet信息服務(IIS)5.0 中利用了緩衝區溢出,2003年,SQL Slammer蠕蟲病毒破壞了運行Microsoft SQL Server 2000的機器。
2003年,許可的Xbox遊戲中出現的緩衝區溢出已被利用,允許未經許可的軟體(包括自製遊戲)在控制台上運行而無需進行硬體修改,稱為modchips。PS2 Independence Exploit也使用緩衝區溢出來實現PlayStation 2的相同功能。使用“塞爾達傳說:暮光公主”中的緩衝區溢出,Twilight黑客在Wii上實現了相同的功能。
技術說明
由於邊界檢查不足,寫入緩衝區的數據也會破壞與目標緩衝區相鄰的記憶體地址中的數據值時發生緩衝區溢出。 將數據從一個緩衝區複製到另一個緩衝區而不先檢查數據是否適合目標緩衝區時,可能會發生這種情況。
例子:有關基於堆疊的溢出的更多信息:堆疊緩衝區溢出。在下面用C表示的例子中,程式有兩個在記憶體中相鄰的變數:一個8位元組長的字元串緩衝區A和一個兩位元組的大端位元組B。
最初,A只包含零位元組,而B包含數字1979。
變數名字 | A | B |
value | [null string] | 1979 |
hex value | 00 00 00 00 00 00 00 00 | 07 BB |
程式試圖在A緩衝區中存儲ASCII編碼的空字元結尾字元串“excess”。
“過多”長度為9個字元,編碼為10個位元組,包括空終止符,但A只能占用8個位元組。 如果沒有檢查字元串的長度,它也會覆蓋B的值:
變數名字 | A | B |
value | "e" "x" "c" "e" "s" "s" "i" "v" | 25856 |
hex value | 65 78 63 65 73 73 69 76 | 65 00 |
B的值已被無意中替換為由部分字元串形成的數字。 在這個例子中,“e”後跟一個零位元組將變成25856.在分配的記憶體末尾寫入數據有時可以被作業系統檢測到,以產生終止該過程的分段錯誤錯誤。
為了防止在此示例中發生緩衝區溢出,可以使用strncpy替換對strcpy的調用,strncpy將A的最大容量作為附加參數,並確保將不超過此數量的數據寫入A:
請注意,上面的代碼也沒有問題; 雖然此次阻止了緩衝區溢出,但如果源字元串的長度大於或等於緩衝區的大小(傳遞給函式的第三個參數),則strncpy庫函式不會終止目標緩衝區,因此A 在這種情況下,它不是空終止的,不能被視為有效的C風格的字元串。
保護對策
1.程式語言的選擇;
2.使用安全的庫;
3.緩衝區溢出保護;
4.指針保護;
5.可執行空間保護;
6.地址空間布局隨機化;
7.深度包檢查;
8.測試.