溢出漏洞利用原理及其檢測原理——就是代碼注入shellcode,檢測可以利用靜態簽名


【漏洞解析】舉個小栗子說明溢出漏洞利用原理及其檢測原理

溢出漏洞利用,是指在存在緩存溢出安全漏洞的計算機中,攻擊者可以用超出常規長度的字符數來填滿一個域,通常是內存區地址。在某些情況下,這些過量的字符能夠作為“可執行”代碼來運行。從而使得攻擊者可以不受安全措施的約束進行攻擊行為。本文以實例詳細說明溢出漏洞的利用過程,感興趣的朋友們來動手操作一把吧!

一、溢出漏洞利用概述

溢出漏洞利用,是指在存在緩存溢出安全漏洞的計算機中,攻擊者可以用超出常規長度的字符數來填滿一個域,通常是內存區地址。在某些情況下,這些過量的字符能夠作為“可執行”代碼來運行。從而使得攻擊者可以不受安全措施的約束進行攻擊行為。

下面以棧布局說明溢出漏洞利用過程。

正常棧布局

RBP : 棧基地址寄存器,指向棧底地址;

RSP : 棧頂寄存器,指向棧頂地址;

RIP:指令地址寄存器,指向指令所在地址。

函數調用時,當前函數的下一個執行命令入棧(RIP,即RET返回地址),RBP入棧,然后把當前RSP的值給RBP;

RSP根據函數執行而移動,根據空間需要移動所指位置,例如入棧局部變量,RSP的值會跟着減小,保證RSP一直指向棧頂。

棧溢出利用過程說明

棧上的內容填充是從低地址向高地址填充的。

請注意,我們開始使壞啦:
1)給var1填充巧妙構造的超長字符串,超過var1高地址(0x7fffffffdee8),並繼續覆蓋更高地址的內容,可以看到會把RBP(0x7fffffffdef0)和RET返回地址(0x7fffffffdef8)都給覆蓋了;
2)RET返回地址指向var1地址(0x7fffffffdee8),var1里面有我們精心制造的字符串,說白了,有我們的惡意代碼;
3)被調用函數執行返回命令時,會讀取RET返回地址,便會讀取var1里面的惡意代碼,並進行執行,無意中執行了惡意代碼。

也就是,通過緩沖區溢出,我們能改變程序原有的執行流程,去執行我們准備好的代碼。
直觀示意請見下面的溢出棧布局圖:

二、存有溢出漏洞的代碼

  • 漏洞代碼內容

代碼很簡單,可以看到這段代碼用了危險函數strcpy!!

  • 漏洞編譯並運行
  • 編譯命令


注意后面兩個參數必須要加上,要不然,后續的漏洞利用會比較麻煩,這兩個參數是關閉linux系統的堆棧溢出保護機制。
-z execstack:表示允許棧中存放可執行代碼;
-fno-stack-protector:表示關閉堆棧保護機制,可以任意覆蓋RIP的值,如果編譯沒有加上這個參數,程序執行過程會進行值(被稱為金絲雀值)校驗,看RIP是否被篡改了,如果篡改了,說明發生了棧溢出,會調用__stack_chk_fail函數,進行安全退出並丟出一個錯誤。
我們這次是為了研究溢出漏洞利用的流程和原理,不是進行高級漏洞挖掘研究,所以,先關閉系統本身的保護機制。

  • 正常結果

  • 異常結果


字符串過長,程序崩潰了。

三、GDB下的漏洞利用執行

  • RIP控制
  • 設定斷點后,執行查看寄存器內容和棧內容

  • 繼續執行,填充288個B字符后的棧內容情況

  • 繼續執行,strcpy執行完畢返回,查看寄存器和棧內容,可以看到rbp被覆蓋了,但是rip並沒有被覆蓋,從棧中可以看出,是嘗試把0x4242424242424242賦值給rip,然而linux 64位系統的rip最大值是0x00007fffffffffff,因而,rip控制失敗。


  • 調整輸入字符串,再次嘗試控制RIP

可以計算返回地址的相對位置:0x7fffffffdd38- 0x7fffffffdc30=0x108=264(十進制)
因而,可以構造字符串:”B” * 264 + “C” * 6 通過gdb調試,可以看到,這次我們能控制rip的取值了,是我們嘗試的0x434343434343。

基於我們不斷探索的精神,我們繼續嘗試,把RIP指向緩存起始地址,即我們可以控制內容的地方。構造字符串:”B” * 264 + “\x7f\xff\xff\xff\xdc\x40″(反序),因為是小端模式,因此內存地址需要反序。

OK,目前為止,我們已經可以控制RIP指向我們的緩存空間了,下一步就是把shellcode注入到我們的緩存空間中,見下面小節。

  • Shellcode代碼注入

Shellcode是一串機器可以直接識別的操作碼,一般短小精悍,可以實現很多關鍵功能,是溢出漏洞利用的完美搭檔。

Shellcode可以自己編寫,也可以使用MetaSploit的shellcode生成器來生成。
當然,也可以直接從網上找現成的使用。

推薦個網站:https://www.exploit-db.com/shellcode/,里面有各種操作系統的各種shellcode代碼,可以用來研究學習。

攻擊者可以利用shellcode實現不同的攻擊用途。

例如:可以實現蠕蟲木馬的下載;可以打開被淪陷系統的端口,以便接收C&C控制服務器的指令;也可以提權運行系統的命令行shell;以及獲取系統關鍵資料文件等等。

我們這次用shellcode實現對系統的關鍵文件(/etc/passwd)的讀取。

在gdb設定斷點后,開始執行查看棧內容,可以看到shellcode內容和返回地址都已經填充成我們期望的數據。


繼續執行,可以看到我們成功調出來了系統的關鍵文件(/etc/passwd)的內容!

細心的小伙伴會發現,我在shellcode之前填充了好多”\x90”,這是NOP空命令,作為緩沖作用,rip的值落在這個范圍內都會順利下滑到shellcode正常執行。
也就是說,就算rip地址稍微有點偏差,也會正常利用成功。

四、實際環境下的漏洞利用執行

  • 實際環境執行gdb調試好的字符串參數

直接運行,失敗!

檢查打印信息,我們會發現緩存地址變化非常隨機,無法提前預知,就算咱們有NOP緩沖區也失效了。


這正是linux的另一種保護機制,通過地址隨機化,防止溢出利用攻擊。

那先關閉這個機制,再次驗證。

關閉這個機制的命令:sudo bash -c “echo 0 > /proc/sys/kernel/randomize_va_space”

  • 關閉randomize_va_space后的實際環境運行情況

OK,利用成功!

五、溢出漏洞利用樣本

在這個小節,我們自己編寫個溢出漏洞利用樣本,並進行漏洞利用攻擊。

  • 溢出漏洞利用樣本程序
  • 計算緩存大小,並獲取rsp寄存器的值,用這個值預估返回地址(retAddr = rsp + RSP_RET_DIFF+ adjustment)。

  • 申請緩存存儲空間,並在其中輸入我們期望的內容(NOP段+shellcode+填充內容+返回地址),填充內容是為了構造合適的字符串長度,保證棧上返回地址內容被覆蓋成我們期望的返回地址。

  • 調用我們之前編譯好的有漏洞程序victim。

一點小提醒:為了防止內存泄漏,malloc分配的空間使用完畢要記得釋放,對應的指針也要置為NULL,防止指針誤用。

  • 溢出漏洞利用程序編譯運行
  • 編譯

  • 運行


直接運行發現出問題了,不能正常執行!

查看打印信息,可得知我們用的返回地址(0x7fffffffde60)跟緩存的起始地址(0x7fffffffdc80)差距很大,因而程序不能進入shellcode代碼區正常執行。

因此,需要調整下返回地址,返回地址構成是:(retAddr = rsp + RSP_RET_DIFF+ adjustment),我們可以通過參數調整這個adjustment值,見下面小節。

  • 調整返回地址偏差,繼續運行樣本


OK,正常執行我們的shellcode代碼!

對比返回地址(0x7fffffffdc9c)和緩存起始地址(0x7fffffffdc80),可以發現兩者並不一致,返回地址是在緩存起始地址之后,但也正常執行了。

原因很簡單,因為我們在緩存里面填充了很多NOP作為緩沖,返回地址只要落在NOP緩沖區任何一個地方,都能下滑到shellcode代碼區進行正常運行。

可能有人會問,都能看到緩存起始地址了,干嘛還折騰用rsp預估返回地址呢,多麻煩呀?

大家可以想想實際情況,應該沒有哪個應用程序會主動暴露緩存起始地址(我們的漏洞程序純粹為了調試,把緩存的起始地址給打印出來了),因而需要一個參考地址進行預估返回地址是多少,所以我們就用了rsp值作為參考地址。

我們已經了解了溢出漏洞利用原理,下面我們開始看看針對這種漏洞的檢測原理。

六、溢出漏洞利用檢測

  • 溢出漏洞利用檢測思路

目前比較常用的主要有三種:基於漏洞特征檢測、基於Exploit特征檢測、基於攻擊特征檢測。
1)基於漏洞特征檢測:對漏洞攻擊手段和技術細節比較了解后,研究其觸發攻擊的必要條件,可以分析出其對應的識別規則,例如緩存區溢出檢測、目錄遍歷檢測、遠程命令注入檢測、遠程文件包含檢測等;
2)基於Exploit特征檢測:從漏洞利用程序中分析獨特特征,做為識別規則,例如返回地址檢測、ROP Chain檢測等;
3)基於攻擊特征檢測:通過檢測漏洞利用相關的相對獨立的組件來發現攻擊,例如shellcode代碼檢測、畸形參數攻擊檢測等等。

  • 基於漏洞特征檢測
  • 本文中的漏洞程序檢測

從前文可知,victim被攻擊的觸發條件正是輸入一段超長的參數,導致溢出而被利用攻擊;
檢測方法就是對victim的輸入參數進行檢查,如果超過一定值(例如256),就要產生告警發現攻擊行為。
下圖的紅線之間的就是輸入參數。

  • 實際案例的檢測機制:Microsoft Windows DCOM RPC接口長主機名遠程緩沖區溢出漏洞(MS03-026)(CVE-2003-0352)

沖擊波蠕蟲就是利用這個漏洞進行傳播攻擊的,Windows Dcom RPC的主機名字段一般不是很長,服務端用棧緩存區存儲這個值,但是拷貝時沒有做長度檢查,導致一個超長的串觸發溢出執行任意指令。

檢測方法:解碼RPC協議,獲取主機名,檢查其長度,如果超過一定值,就要告警發現攻擊行為。

下圖的紅線之間的就是主機名(夠長吧。。)

  • 基於Exploit特征檢測
  • 本文中的漏洞利用檢測

從victim輸入參數進行分析,可以看到返回地址非常明顯,可以作為檢測規則。
發現輸入參數有返回地址,就要告警有攻擊行為。

下圖的紅線所標識的就是返回地址特征。

  • 實際案例的檢測機制:Microsoft Windows工作站服務遠程緩沖區溢出漏洞(MS03-049)(CVE-2003-0812)

可以分析出帶有返回地址的匹配特征。

  • 基於攻擊特征檢測
  • 本文中的漏洞利用檢測

可以通過識別輸入參數的shellcode特征進行匹配,如果參數包含shellcode肯定是異常行為。

同樣,對於我們的溢出漏洞利用樣本,進行靜態分析,如果檢測到有shellcode,就可以說明這個樣本文件存在異常。

  • 實際案例的檢測機制:Microsoft Windows DCOM RPC接口長主機名遠程緩沖區溢出漏洞(MS03-026)

Exploit中夾帶的是典型的自解碼MetaSploit Shellcode,對於這種Shellcode的解碼器做粗略的靜態匹配檢測其實只要匹配“\xd9\x74\x24\xf4”就可以了。

七、總結

  • 有興趣的小伙伴們,可以親自動手操作一把漏洞利用過程,一定會有不一樣的收獲~
  • 研發同學們在后續的開發過程中,除了實現功能和性能,還要留意自己代碼的安全性,做好輸入檢查,防止被黑客利用。


免責聲明!

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



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