2018年1月18日 星期四

緩衝區溢出攻擊介紹

大家都知道緩衝區溢出是一種普遍、而且危險性極強的漏洞,在各種作業系統、應用軟體中廣泛存在。利用緩衝區溢出攻擊,可以導致程序運行失敗、系統當機、重新啟動等後果。

更為嚴重的是,可以利用它執行非授權指令,甚至可以取得系統特權,進而進行各種非法操作。

緩衝區溢出攻擊有多種英文名稱:buffer overflow,buffer overrun,smash the stack,trash the stack,scribble the stack, mangle the stack, memory leak,overrun screw;它們指的都是同一種攻擊手段。第一個緩衝區溢出攻擊–Morris蠕蟲,發生在十年前,它曾造成了全世界6000多台網絡伺服器癱瘓。

本文將分析緩衝區溢出的原理;


研究各種類型的緩衝區溢出漏洞和攻擊手段;

最後,還將著重研究各種防禦手段,用來消除這些漏洞所造成的影響。

一、 緩衝區溢出的原理
通過往程序的緩衝區寫超出其長度的內容,造成緩衝區的溢出,從而破壞程序的堆棧,使程序轉而執行其它指令,以達到攻擊的目的。造成緩衝區溢出的原因是程序中沒有仔細檢查用戶輸入的參數。例如下面程序:

void function(char *str) {
char buffer[16]; //數組溢出
strcpy(buffer,str);
}

上面的strcpy將直接吧str中的內容copy到buffer中。這樣只要str的長度大於16,就會造成buffer的溢出,使程序運行出錯。存在象strcpy這樣的問題的標準函數還有strcat,sprintf,vsprintf,gets,scanf等。

當然,隨便往緩衝區中填東西造成它溢出一般只會出現「分段錯誤」(Segmentation fault),而不能達到攻擊的目的。最常見的手段是通過製造緩衝區溢出使程序運行一個用戶shell,再通過shell執行其它命令。如果該程序屬於root且有suid權限的話,攻擊者就獲得了一個有root權限的shell,可以對系統進行任意操作了。

緩衝區溢出攻擊之所以成為一種常見安全攻擊手段其原因在於緩衝區溢出漏洞太普遍了,並且易於實現。而且,緩衝區溢出成為遠程攻擊的主要手段其原因在於緩衝區溢出漏洞給予了攻擊者他所想要的一切:植入並且執行攻擊代碼。被植入的攻擊代碼以一定的權限運行有緩衝區溢出漏洞的程序,從而得到被攻擊主機的控制權。

在1998年Lincoln實驗室用來評估入侵檢測的的5種遠程攻擊中,有2種是緩衝區溢出。而在1998年CERT的13份建議中,有9份是是與緩衝區溢出有關的,在1999年,至少有半數的建議是和緩衝區溢出有關的。在Bugtraq的調查中,有2/3的被調查者認為緩衝區溢出漏洞是一個很嚴重的安全問題。

緩衝區溢出漏洞和攻擊有很多種形式,會在第二節對他們進行描述和分類。相應地防衛手段也隨者攻擊方法的不同而不同,將在第四節描述,它的內容包括針對每種攻擊類型的有效的防衛手段。

二、緩衝區溢出的漏洞和攻擊
緩衝區溢出攻擊的目的在於擾亂具有某些特權運行的程序的功能,這樣可以使得攻擊者取得程序的控制權,如果該程序具有足夠的權限,那麼整個主機就被控制了。一般而言,攻擊者攻擊root程序,然後執行類似「exec(sh)」的執行代碼來獲得root權限的shell。為了達到這個目的,攻擊者必須達到如下的兩個目標:

在程序的地址空間裡安排適當的代碼。

通過適當的初始化寄存器和內存,讓程序跳轉到入侵者安排的地址空間執行。

根據這兩個目標來對緩衝區溢出攻擊進行分類。

在二.1節,將描述攻擊代碼是如何放入被攻擊程序的地址空間的。

在二.2節,將介紹攻擊者如何使一個程序的緩衝區溢出,並且執行轉移到攻擊代碼(這個就是「溢出」的由來)。

在二.3節,將綜合前兩節所討論的代碼安排和控制程序執行流程的技術。

二.1 在程序的地址空間裡安排適當的代碼的方法
有兩種在被攻擊程序地址空間裡安排攻擊代碼的方法:

1、植入法:

攻擊者向被攻擊的程序輸入一個字符串,程序會把這個字符串放到緩衝區里。這個字符串包含的資料是可以在這個被攻擊的硬體平台上運行的指令序列。在這裡,攻擊者用被攻擊程序的緩衝區來存放攻擊代碼。緩衝區可以設在任何地方:堆棧(stack,自動變量)、堆(heap,動態分配的內存區)和靜態資料區。

2、利用已經存在的代碼:

有時,攻擊者想要的代碼已經在被攻擊的程序中了(本身存在溢出問題的代碼),攻擊者所要做的只是對代碼傳遞一些參數。比如,攻擊代碼要求執行「exec (「/bin/sh」)」,而在libc庫中的代碼執行「exec (arg)」,其中arg使一個指向一個字符串的指針參數,那麼攻擊者只要把傳入的參數指針改向指向」/bin/sh」。

二.2 控制程序轉移到攻擊代碼的方法
所有的這些方法都是在尋求改變程序的執行流程,使之跳轉到攻擊代碼。最基本的就是溢出一個沒有邊界檢查或者其它弱點的緩衝區,這樣就擾亂了程序的正常的執行順序。通過溢出一個緩衝區,攻擊者可以用暴力的方法改寫相鄰的程序空間而直接跳過了系統的檢查。

分類的基準是攻擊者所尋求的緩衝區溢出的程序空間類型。原則上是可以任意的空間。實際上,許多的緩衝區溢出是用暴力的方法來尋求改變程序指針的。這類程序的不同之處就是程序空間的突破和內存空間的定位不同。主要有以下三種: 1、活動紀錄(Activation Records):

每當一個函數調用發生時,調用者會在堆棧中留下一個活動紀錄,它包含了函數結束時返回的地址。攻擊者通過溢出堆棧中的自動變量,使返回地址指向攻擊代碼。通過改變程序的返回地址,當函數調用結束時,程序就跳轉到攻擊者設定的地址,而不是原先的地址。這類的緩衝區溢出被稱為堆棧溢出攻擊(Stack Smashing Attack),是目前最常用的緩衝區溢出攻擊方式。

2、函數指針(Function Pointers):

函數指針可以用來定位任何地址空間。例如:「void (* foo)」聲明了一個返回值為void的函數指針變量foo。所以攻擊者只需在任何空間內的函數指針附近找到一個能夠溢出的緩衝區,然後溢出這個緩衝區來改變函數指針。在某一時刻,當程序通過函數指針調用函數時,程序的流程就按攻擊者的意圖實現了。它的一個攻擊範例就是在Linux系統下的superprobe程序。

3、長跳轉緩衝區(Longjmp buffers):

在C語言中包含了一個簡單的檢驗/恢復系統,稱為setjmp/longjmp。意思是在檢驗點設定「setjmp(buffer)」,用「longjmp(buffer)」來恢復檢驗點。然而,如果攻擊者能夠進入緩衝區的空間,那麼「longjmp(buffer)」實際上是跳轉到攻擊者的代碼。象函數指針一樣,longjmp緩衝區能夠指向任何地方,所以攻擊者所要做的就是找到一個可供溢出的緩衝區。一個典型的例子就是Perl 5.003的緩衝區溢出漏洞;攻擊者首先進入用來恢復緩衝區溢出的的longjmp緩衝區,然後誘導進入恢復模式,這樣就使Perl的解釋器跳轉到攻擊代碼上了。

二.3代碼植入和流程控制技術的綜合分析
最簡單和常見的緩衝區溢出攻擊類型就是在一個字符串里綜合了代碼植入和活動紀錄技術。攻擊者定位一個可供溢出的自動變量,然後向程序傳遞一個很大的字符串,在引發緩衝區溢出,改變活動紀錄的同時植入了代碼。這個是由Levy指出的攻擊的模板。因為C在習慣上只為用戶和參數開闢很小的緩衝區,因此這種漏洞攻擊的實例十分常見。

代碼植入和緩衝區溢出不一定要在在一次動作內完成。攻擊者可以在一個緩衝區內放置代碼,這是不能溢出的緩衝區。然後,攻擊者通過溢出另外一個緩衝區來轉移程序的指針。這種方法一般用來解決可供溢出的緩衝區不夠大(不能放下全部的代碼)的情況。

如果攻擊者試圖使用已經常駐的代碼而不是從外部植入代碼,他們通常必須把代碼作為參數調用。舉例來說,在libc(幾乎所有的C程序都要它來連接)中的部分代碼段會執行「exec(something)」,其中somthing就是參數。攻擊者然後使用緩衝區溢出改變程序的參數,然後利用另一個緩衝區溢出使程序指針指向libc中的特定的代碼段。

三、 緩衝區溢出攻擊的實驗分析
2000年1月,Cerberus 安全小組發布了微軟的IIS 4/5存在的一個緩衝區溢出漏洞。攻擊該漏洞,可以使Web伺服器崩潰,甚至獲取超級權限執行任意的代碼。目前,微軟的IIS 4/5 是一種主流的Web伺服器程序;因而,該緩衝區溢出漏洞對於網站的安全構成了極大的威脅;它的描述如下:

瀏覽器向IIS提出一個HTTP請求,在域名(或IP位址)後,加上一個文件名,該文件名以「.htr」做後綴。於是IIS認為客戶端正在請求一個「.htr」文件,「.htr」擴展文件被映像成ISAPI(Internet Service API)應用程式,IIS會復位向所有針對「.htr」資源的請求到 ISM.DLL程序 ,ISM.DLL 打開這個文件並執行之。

瀏覽器提交的請求中包含的文件名存儲在局部變量緩衝區中,若它很長,超過600個字符時,會導致局部變量緩衝區溢出,覆蓋返回地址空間,使IIS崩潰。更進一步,可以在緩衝區中植入一段精心設計的代碼,可以使之以系統超級權限運行。

四、緩衝區溢出攻擊的防範方法
緩衝區溢出攻擊占了遠程網絡攻擊的絕大多數,這種攻擊可以使得一個匿名的Internet用戶有機會獲得一台主機的部分或全部的控制權。如果能有效地消除緩衝區溢出的漏洞,則很大一部分的安全威脅可以得到緩解。

目前有四種基本的方法保護緩衝區免受緩衝區溢出的攻擊和影響。

1.通過作業系統使得緩衝區不可執行,從而阻止攻擊者植入攻擊代碼。

2.強制寫正確的代碼的方法。

3.利用編譯器的邊界檢查來實現緩衝區的保護。這個方法使得緩衝區溢出不可能出現,從而完全消除了緩衝區溢出的威脅,但只是相對而言。

來源:CSDN博客

沒有留言:

張貼留言