緩沖區溢出漏洞攻擊原理


轉自互聯網

0x00 緩沖區溢出概念

    緩沖區溢出是指當計算機向緩沖區內填充數據位數時超過了緩沖區本身的容量溢出的數據覆蓋合法數據上,

 

理想的情況是程序檢查數據長度並不允許輸入超過緩沖區長度的字符,但是絕大多數程序都會假設數據長度總是與所分配的儲存空間相匹配,這就為緩沖區溢出埋下隱患,操作系統所使用的緩沖區,又被稱為"堆棧"。在各個操作進程之間,指令會被臨時儲存在"堆棧"當中,"堆棧"也會出現緩沖區溢出。

 

0x01 緩沖區溢出原理

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

  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(Set User ID,)權限的話,攻擊者就獲得了一個有root權限的shell可以對系統進行任意操作了。


 

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

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

 

0x02 緩沖區溢出漏洞攻擊方式

    緩沖區溢出漏洞可以使任何一個有黑客技術的人取得機器的控制權甚至是最高權限。一般利用緩沖區溢出漏洞攻擊root程序,大都通過執行類似“exec(sh)”的執行代碼來獲得root 的shell。黑客要達到目的通常要完成兩個任務,就是在程序的地址空間里安排適當的代碼和通過適當的初始化寄存器和存儲器,讓程序跳轉到安排好的地址空間執行。

     

1)在程序的地址空間里安排適當的代碼

       在程序的地址空間里安排適當的代碼往往是相對簡單的。如果要攻擊的代碼在所攻擊程序中已經存在了,那么就簡單地對代碼傳遞一些參數,然后使程序跳轉到目標中就可以完成了。攻擊代碼要求執行“exec(‘/bin/sh’)”,而在libc庫中的代碼執行“exec(arg)”,其中的“arg”是個指向字符串的指針參數,只要把傳入的參數指針修改指向“/bin/sh”,然后再跳轉到libc庫中的響應指令序列就可以了。當然,很多時候這個可能性是很小的,那么就得用一種叫“植入法”的方式來完成了。

 

當向要攻擊的程序里輸入一個字符串時,程序就會把這個字符串放到緩沖區里,這個字符串包含的數據是可以在這個所攻擊的目標的硬件平台上運行的指令序列。緩沖區可以設在:堆棧(自動變量)、堆(動態分配的)和靜態數據區(初始化或者未初始化的數據)等的任何地方。也可以不必為達到這個目的而溢出任何緩沖區,只要找到足夠的空間來放置這些攻擊代碼就夠了。

    

2)控制程序轉移到攻擊代碼的形式

      緩沖區溢出漏洞攻擊都是在尋求改變程序的執行流程,使它跳轉到攻擊代碼,最為基本的就是溢出一個沒有檢查或者其他漏洞的緩沖區,這樣做就會擾亂程序的正常執行次序。通過溢出某緩沖區,可以改寫相近程序的空間而直接跳轉過系統對身份的驗證。原則上來講攻擊時所針對的緩沖區溢出的程序空間可為任意空間。但因不同地方的定位相異,所以也就帶出了多種轉移方式。

   (1)Function Pointers(函數指針)

       在程序中,“void (* foo) ( )”聲明了個返回值為“void” Function Pointers的變量“foo”。Function Pointers可以用來定位任意地址空間,攻擊時只需要在任意空間里的Function Pointers鄰近處找到一個能夠溢出的緩沖區,然后用溢出來改變Function Pointers。當程序通過Function Pointers調用函數,程序的流程就會實現。

   (2)Activation Records(激活記錄)

       當一個函數調用發生時,堆棧中會留駐一個Activation Records,它包含了函數結束時返回的地址。執行溢出這些自動變量,使這個返回的地址指向攻擊代碼,再通過改變程序的返回地址。當函數調用結束時,程序就會跳轉到事先所設定的地址,而不是原來的地址。這樣的溢出方式也是較常見的。

      3)植入綜合代碼和流程控制

      常見的溢出緩沖區攻擊類是在一個字符串里綜合了代碼植入和Activation Records。攻擊時定位在一個可供溢出的自動變量,然后向程序傳遞一個很大的字符串,在引發緩沖區溢出改變Activation Records的同時植入代碼(權因C在習慣上只為用戶和參數開辟很小的緩沖區)。植入代碼和緩沖區溢出不一定要一次性完成,可以在一個緩沖區內放置代碼(這個時候並不能溢出緩沖區),然后通過溢出另一個緩沖區來轉移程序的指針。這樣的方法一般是用於可供溢出的緩沖區不能放入全部代碼時的。如果想使用已經駐留的代碼不需要再外部植入的時候,通常必須先把代碼做為參數。在libc(熟悉C的朋友應該知道,現在幾乎所有的C程序連接都是利用它來連接的)中的一部分代碼段會執行“exec(something)”,當中的something就是參數,使用緩沖區溢出改變程序的參數,然后利用另一個緩沖區溢出使程序指針指向libc中的特定的代碼段。

程序編寫的錯誤造成網絡的不安全性也應當受到重視,因為它的不安全性已被緩沖區溢出表現得淋漓盡致了。

 

0x03 緩沖區溢出的保護方法

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

      1)強制寫正確的代碼的方法

      編寫正確的代碼是一件非常有意義但耗時的工作,特別像編寫C語言那種具有容易出錯傾向的程序(如:字符串的零結尾),這種風格是由於追求性能而忽視正確性的傳統引起的。盡管花了很長的時間使得人們知道了如何編寫安全的程序,具有安全漏洞的程序依舊出現。因此人們開發了一些工具和技術來幫助經驗不足的程序員編寫安全正確的程序。雖然這些工具幫助程序員開發更安全的程序,但是由於C語言的特點,這些工具不可能找出所有的緩沖區溢出漏洞。所以,偵錯技術只能用來減少緩沖區溢出的可能,並不能完全地消除它的存在。除非程序員能保證他的程序萬無一失,否則還是要用到以下部分的內容來保證程序的可靠性能。

       2)通過操作系統使得緩沖區不可執行,從而阻止攻擊者殖入攻擊代碼

      這種方法有效地阻止了很多緩沖區溢出的攻擊,但是攻擊者並不一定要殖入攻擊代碼來實現緩沖區溢出的攻擊,所以這種方法還是存在很多弱點的。

      3)利用編譯器的邊界檢查來實現緩沖區的保護

     這個方法使得緩沖區溢出不可能出現,從而完全消除了緩沖區溢出的威脅,但是相對而言代價比較大。

      4)在程序指針失效前進行完整性檢查

      這樣雖然這種方法不能使得所有的緩沖區溢出失效,但它的確確阻止了絕大多數的緩沖區溢出攻擊,而能夠逃脫這種方法保護的緩沖區溢出也很難實現。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM