1.概念
緩沖區溢出是指當計算機用數據位填充緩沖區時,溢出的超過緩沖區本身容量的數據被合法數據覆蓋。理想情況下,程序檢查數據長度,不允許輸入超過緩沖區長度的字符,但大多數程序都假設數據長度總是與分配的存儲空間相匹配,這就為緩沖區溢出埋下了隱患。操作系統使用的緩沖區也稱為“堆棧”。在每個操作過程中,指令會被臨時存儲在“堆棧”中。
2.損害
在當前的網絡和分布式系統安全中,50%以上都廣泛應用於緩沖區溢出,最著名的例子就是1988中利用fingerd漏洞的蠕蟲。在緩沖區溢出中,最危險的是堆棧溢出,因為入侵者可以利用堆棧溢出在函數返回時改變返回程序的地址,使其可以跳轉到任意地址。壹種危害是程序崩潰導致拒絕服務,另壹種是跳轉執行壹個惡意代碼,比如獲取壹個外殼,然後為所欲為。
3.緩沖攻擊
1.緩沖區溢出原理
通過將超出其長度的內容寫入程序的緩沖區,使緩沖區溢出,從而破壞程序的堆棧,使程序執行其他指令,達到攻擊的目的。緩沖區溢出的原因是程序中沒有仔細檢查用戶輸入的參數。例如以下程序:
voidfunction(char*str){
char buffer[16];
strcpy(緩沖區,str);
}
上面的Strcpy()會直接將str中的內容復制到buffer中。這樣,只要str的長度大於16,就會造成緩沖區溢出,使程序運行不正確。像strcpy這樣有問題的標準函數有strcat()、sprintf()、vsprintf()、gets()、scanf()等等。
當然,隨便填充緩沖區使其溢出壹般只會導致“Segmentationfault”,達不到攻擊的目的。最常見的方法是通過創建緩沖區溢出使程序運行壹個用戶外殼,然後通過外殼執行其他命令。如果程序屬於root,並且擁有suid權限,那麽攻擊者就會得到壹個擁有root權限的外殼,可以隨意操作系統。
緩沖區溢出攻擊之所以成為壹種常見的安全攻擊手段,是因為緩沖區溢出漏洞太常見,太容易實現。而且緩沖區溢出已經成為遠程攻擊的主要手段,因為緩沖區溢出漏洞給了攻擊者想要的壹切:植入和執行攻擊代碼。植入的攻擊代碼以壹定權限運行具有緩沖區溢出漏洞的程序,從而獲得被攻擊主機的控制權。
在1998中,林肯實驗室用來評估入侵檢測的五種遠程攻擊中有兩種是緩沖區溢出。在1998中,CERT的13條建議中,有9條與緩沖區溢出有關,在1999中,至少有壹半與緩沖區溢出有關。在Bugtraq的調查中,三分之二的受訪者認為緩沖區溢出漏洞是壹個非常嚴重的安全問題。
緩沖區溢出漏洞和攻擊有多種形式,我們將在第二部分對其進行描述和分類。相應地,防禦手段隨著攻擊方式的不同而不同,這將在第四節中描述,其內容包括針對每種攻擊類型的有效防禦手段。
二、緩沖區溢出漏洞和攻擊
緩沖區溢出攻擊的目的是幹擾具有壹定權限的程序的功能,從而使攻擊者獲得對程序的控制。如果程序有足夠的權限,整個主機就被控制了。壹般來說,攻擊者攻擊root程序,然後執行類似於“exec(sh)”的執行代碼,獲得具有root權限的外殼。為了實現這壹目標,攻擊者必須實現以下兩個目標:
1.在程序的地址空間中安排適當的代碼。
2.通過適當的初始化寄存器和內存,使程序跳轉到入侵者安排的地址空間。
根據這兩個目標,對緩沖區溢出攻擊進行了分類。在II.1節中,我們將描述攻擊代碼是如何放入被攻擊程序的地址空間中的。在2.2節中,我們將介紹攻擊者如何使程序的緩沖區溢出,並將執行轉移到攻擊代碼(這就是“溢出”的由來)。在第II.3節中,將整合前兩節中討論的代碼排列和程序執行控制技術。
二。1在程序地址空間中安排適當代碼的方法
在被攻擊程序的地址空間中排列攻擊代碼有兩種方法:
1,植入方式:
攻擊者在被攻擊的程序中輸入壹個字符串,程序會把這個字符串放入緩沖區。該字符串中包含的數據是可以在這個被攻擊的硬件平臺上運行的指令序列。在這裏,攻擊者使用被攻擊程序的緩沖區來存儲攻擊代碼。緩沖區可以設置在任何地方:堆棧(自動變量)、堆(動態分配的內存區)和靜態數據區。
2、利用現有代碼:
有時候,攻擊者想要的代碼已經在被攻擊的程序中了,攻擊者要做的就是給代碼傳遞壹些參數。比如攻擊代碼要求執行“exec ("/bin/sh ")”,而libc庫中的代碼執行“exec(arg)",其中arg做壹個指向字符串的指針參數,那麽攻擊者只需要改變傳入參數指針指向"/bin/sh "。
II.2將控制程序轉移到攻擊代碼的方法
所有這些方法都是尋求改變程序的執行過程,使其跳轉到攻擊代碼。最基本的就是在沒有邊界檢查或者其他弱點的情況下溢出壹個緩沖區,擾亂了程序的正常執行順序。通過溢出緩沖區,攻擊者可以暴力重寫相鄰的程序空間,直接跳過系統檢查。
分類標準是攻擊者尋找緩沖區溢出的程序空間的類型。原則上,它可以是任何空間。事實上,許多緩沖區溢出都試圖通過暴力方法來改變程序指針。這類程序的區別在於程序空間的突破和內存空間的定位不同。主要有以下三種:1和ActivationRecords:
每當函數調用發生時,調用者都會在堆棧上留下壹條活動記錄,其中包含函數結束時返回的地址。攻擊者通過溢出堆棧中的自動變量,使返回地址指向攻擊代碼。通過改變程序的返回地址,當函數調用結束時,程序跳轉到攻擊者設置的地址,而不是原來的地址。這種緩沖區溢出稱為堆棧溢出攻擊,是目前最常用的緩沖區溢出攻擊。
2.函數指針:
函數指針可以用來定位任何地址空間。比如“void(*foo)()”聲明了壹個函數指針變量foo,它的返回值是void。所以攻擊者只需要在任意空間的函數指針附近找到壹個溢出緩沖區,然後溢出這個緩沖區來改變函數指針。在某個時刻,當程序通過函數指針調用函數時,程序的流程就按照攻擊者的意圖實現了。其攻擊的壹個例子就是Linux系統下的superprobe程序。
3.Longjmpbuffers:
c語言包含壹個簡單的檢查/恢復系統,名為setjmp/longjmp。意思是在檢查點設置“setjmp(buffer)”,用“longjmp(buffer)”恢復檢查點。但是,如果攻擊者可以進入緩沖區的空間,那麽“longjmp(buffer)”實際上就是跳轉到攻擊者的代碼。像函數指針壹樣,longjmp緩沖區可以指向任何地方,所以攻擊者所要做的就是找到壹個溢出的緩沖區。壹個典型的例子是Perl5.003中的緩沖區溢出漏洞;攻擊者首先進入用於恢復緩沖區溢出的longjmp緩沖區,然後被誘導進入恢復模式,使得Perl的解釋器跳轉到攻擊代碼。
2.3代碼植入和流程控制技術綜合分析
最簡單和最常見的緩沖區溢出攻擊類型是在字符串中結合代碼植入和活動記錄技術。攻擊者定位壹個溢出的自動變量,然後向程序傳遞壹個很大的字符串,導致緩沖區溢出,並在嵌入代碼的同時改變活動記錄。這是利維指出的攻擊的模板。因為C習慣上只給用戶和參數開壹個很小的緩沖區,所以這種漏洞攻擊很常見。
代碼植入和緩沖區溢出不必在壹個動作中完成。攻擊者可以將代碼放在壹個緩沖區中,這個緩沖區是不能溢出的。然後,攻擊者通過溢出另壹個緩沖區來轉移程序的指針。這種方法壹般用於解決可用於溢出的緩沖區不夠大(所有代碼都放不下)的情況。
如果攻擊者試圖使用已經駐留的代碼,而不是從外部植入代碼,他們通常必須調用代碼作為參數。比如libc中的壹些代碼段(幾乎所有C程序都需要連接)會執行“exec(something)”,其中something是參數。然後攻擊者利用緩沖區溢出改變程序的參數,再利用另壹個緩沖區溢出使程序指針指向libc中特定的代碼段。
第三,緩沖區溢出攻擊的實驗分析
5438年6月+2000年10月,Cerberus安全小組在Microsoft IIS4/5中發布了壹個緩沖區溢出漏洞。攻擊此漏洞可以使Web服務器崩潰,甚至獲得執行任意代碼的超級權限。目前,微軟的IIS4/5是主流的Web服務器程序。因此,緩沖區溢出漏洞對網站的安全構成了極大的威脅;其描述如下:
瀏覽器向IIS發出HTTP請求,在域名(或IP地址)後添加壹個文件名,文件名中帶有“.”。htr”作為後綴。因此IIS認為客戶端請求的是壹個"。htr "文件,以及。htr”擴展文件映射到ISAPI(InternetServiceAPI)應用程序中。IIS將重置對“”的所有請求。htr”資源到ISM.DLL程序,ISM.DLL將打開這個文件並執行它。
瀏覽器提交的請求中包含的文件名存儲在局部變量緩沖區中。如果很長,超過600個字符,會導致局部變量緩沖區溢出,覆蓋返回地址空間,導致IIS崩潰。再者,可以在2K緩沖區中植入壹段精心設計的代碼,如圖1所示,可以使其以系統超級權限運行。
四、緩沖區溢出攻擊的防範方法
緩沖區溢出攻擊是絕大多數遠程網絡攻擊的原因,這使得匿名互聯網用戶有機會獲得對主機的部分或全部控制。如果能夠有效消除緩沖區溢出漏洞,就可以緩解很大壹部分安全威脅。
目前,有四種基本方法來保護緩沖區免受緩沖區溢出的攻擊和影響。4.1中介紹了操作系統使緩沖區不可執行,從而防止攻擊者植入攻擊代碼。IV.2中介紹了強制編寫正確代碼的方法..在第4.3章,我們介紹了如何使用編譯器的邊界檢查來保護緩沖區。這種方法使緩沖區溢出成為不可能,從而徹底消除了緩沖區溢出的威脅,但代價相對較高。在4.4中,引入了壹個間接的方法,在程序指針失效之前檢查它的完整性。雖然這種方法不能使所有的緩沖區溢出失效,但它可以防止大多數緩沖區溢出攻擊。然後在IV.5中,分析了這種保護方式的兼容性和性能優勢。
四。1非執行緩沖區
通過使被攻擊程序的數據段的地址空間不可執行,攻擊者不可能執行植入被攻擊程序輸入緩沖區的代碼。這種技術被稱為非執行緩沖技術。在早期的Unix系統設計中,代碼段中只允許執行程序代碼。然而,在最近的Unix和MSWindows系統中,為了達到更好的性能和功能,可執行代碼往往被動態地放置在數據段中,這也是緩沖區溢出的根源。為了保持程序的兼容性,不可能讓所有程序的數據段都不可執行。
但是堆棧數據段可以設置為不可執行,這樣可以保證程序的兼容性。Linux和Solaris都發布了這方面的內核補丁。因為幾乎沒有合法的程序會在堆棧上存儲代碼,所以這種做法幾乎不會導致任何兼容性問題,除了Linux中的兩種特殊情況,即可執行代碼必須放入堆棧:
(1)信號傳輸:
Linux向進程發送Unix信號,方法是將代碼釋放到進程堆棧中,然後引發壹個中斷來執行堆棧中的代碼。非執行緩沖區的補丁允許在發送信號時緩沖區是可執行的。
(2)在線重用2)GCC:
發現gcc把可執行代碼放在棧區,以便在線重用。但是,關閉這個功能並不會導致任何問題,只是有些功能似乎無法使用。
非執行棧的保護可以有效應對將代碼嵌入自動變量的緩沖區溢出攻擊,但對其他形式的攻擊沒有作用。通過引用指向常駐程序的指針,可以繞過這種保護。其他攻擊可以通過將代碼植入堆或靜態數據段來繞過保護。
IV.2編寫正確的代碼
寫正確的代碼是壹件很有意義的工作,尤其像用C語言寫壹個風格自由,容易出錯的程序,這是追求性能,忽視正確性的傳統造成的。雖然人們花了很長時間才知道如何編寫安全的程序,但存在安全漏洞的程序還是出現了。因此,人們開發了壹些工具和技術來幫助沒有經驗的程序員編寫安全正確的程序。
最簡單的方法是使用grep搜索源代碼中容易出現漏洞的庫調用,比如對strcpy和sprintf的調用,這些調用不檢查輸入參數的長度。其實所有版本的C的標準庫都有這樣的問題。
此外,人們還開發了壹些先進的錯誤檢測工具,如faultinjection。這些工具的目的是通過人為隨機產生壹些緩沖區溢出來發現代碼的安全漏洞。還有壹些靜態分析工具可以檢測緩沖區溢出的存在。
雖然這些工具幫助程序員開發更安全的程序,但是由於C語言的特性,這些工具不可能發現所有的緩沖區溢出漏洞。所以調試技術只能用來降低緩沖區溢出的可能性,而不能完全杜絕它的存在。