起底CVE-2018-0825堆溢出緩衝區
微軟最近發布了星期二的補丁,旨在修復一系列漏洞,其中14個漏洞被評估為關鍵漏洞。位列榜單之首的是CVE-2018-0825,這是在Windows動態庫StructuredQuery.dll中的一個遠程代碼執行漏洞。
據官方建議稱,該漏洞影響了目前所有的微軟Windows產品。由於這個漏洞還沒有被公開揭露,應用及威脅情報(ATI)研究組決定深入探究一下狀況,並觀望一下微軟事如何處理這種「即時修補」的漏洞。
環境和工具:
微軟Win7x86 SP1被選為目標。此次任務將會用到以下工具:
Ida Pro 6.9 + Hex-Rays Decompiler on Fedora 25
Windows 10 x64 as debugging server
BinDiff plugin
WinDbg
注意:BinDiff官方並不支持Fedora,所以要將其與運行的Ida Pro整合,我們在官方配發的.deb包中得建立一個RPM包。
進行此項研究的大致步驟:
1.建立工作環境
2.獲得兩個版本的目標二進位(StructuredQuery.dll),未打補丁版本和打過補丁的版本
3.在Ida Pro中打開兩個版本,為各自保存相應的.idb分析文件。
運行BinDiff的.idb文件,確定差別並找到漏洞
5.在未打補丁的微軟Windows版本上對漏洞進行測試
詳細步驟
1.建立工作環境
當Windows二進位在Linux系統的Ida Pro中分析時,反彙編器需要一個Windows調試伺服器下載符號。功能名比晦澀難懂的標籤或地址要簡單得多。
我們使用一個Windows10x64 box、IP與Fedora box相連接,運行win32_debugger.exe. Win32_debugger.exe是用Ida Pro(非免費版本)進行傳送,故從Fedora上拷貝到Windows 10上運行。
2.獲取兩種版本的目標二進位
首先,對Windows 7×86 SP1目標窗口的升級狀態進行檢查。在安裝升級的Windows中,上一次更新的安裝時間為01/19/2018。
微軟在二月發布了補丁,所以這個窗口是選取漏洞庫的好地方。
StructuredQuery.dll在%WINDIR%System32里,故我們將其拷入Fedora窗口,在Ida Pro中進行分析。
對於庫中的已修復版本,只需要進行簡單操作:
a.從此漏洞的廠商知道頁面中,找到具體Windows更新包,解決這個問題- KB4074587.
我們將文件命名為:
windows6.1-kb4074587-x86_4acde011f9386e8555109c8a06d406bbcee20a99.msu
可以進行擴展(Windows Vista), 使用工具:
expand –f:* windows6.1-kb4074587-x86_4acde011f9386e8555109c8a06d406bbcee20a99.msuC:\expanded\
該擴展工具在導出目錄中生成了一堆文件和目錄。搜索「StructuredQuery.dll」,會得出想要的結果:
看一下兩個庫文件的屬性(舊的和擴展的),我們可以看到兩個版本之間的差別,儘管文件大小相同:
將文件拷貝到Fedora box進行分析,第二步完成。
3.在Ida Pro中打開二進位
為進行差異分析,在由Ida Pro對二進位進行初始分析後,BinDiff需要二進位.idb文件結果。為更好進行追蹤,我們將舊的二進位重新命名為StructuredQuery_unpatched.dll,新的二進位命名為structuredquery_patched.dll.
打開Ida Pro里的structuredquery_patched.dll,讓其在調試伺服器中下載調試符號。在初始分析完成後,保存並關閉Ida Pro進程。
對StructuredQuery_unpatched.dll重複操作,但這次不要結束進程。
4.在.idb上運行BinDiff在StructuredQuery_unpatched.dll的初始分析完成後,點擊CTRL + 6啟動BinDiff。
點擊Diff Database並瀏覽之前保存的.idb文件。
在BinDiff分析完成後,我們得到以下結果:
查看的最好方法是通過相似性升序。這個案例里我們看到了這些StructuredQuery.dll版本的總共15種功能。
該功能最大的不同是StructuredQuery1::ReadPWSTR(IStream*, ushort **),這為我們提供了一處CVE-2018-0825補丁所在之處的可能線索。
下面列的是兩種庫中相同功能的偽代碼版本,以Hex-Rays反編譯:
總結一下ReadPWSTR()的內容:
a.從pstm (pointer to IStream)中讀取4 bytes,並將值存儲到pv
b.讓CoTaskMemAlloc()分配大小為 2 * pv的內存緩衝區
c.如果分配成功,再次讓IStream_Read()從pstm中再次讀取(2 * pv -2) bytes,並存儲到新分配的緩衝區。
現在來看一下差別。我們注意到新版本中的些許變化:
-pv變數是作為unsigned int,而不是int
-引進了新的局部變數SIZE_T cb
-用(2 * pv), &cb (note the inline casting of constant 2 to a unsigned integer64)啟用了 ULongLongToULong()功能;MSDN(https://msdn.microsoft.com/is-is/library/windows/desktop/bb762429(v=vs.85).aspx)提供了該功能的細節
– cb變數作為參數傳遞給CoTaskMemAlloc(),而不是2 * pv
顯而易見,這些變化是相關聯的,補丁的目的是為驗證pv值在被傳遞前作為CoTaskMemAlloc()的一個論據。
據MSDN所述,CoTaskMemAlloc()採用SIZE_T論據作為分配的內存塊大小,單位是位元組。
IStream_Read()功能採用了ULONG論據,代表功能試圖從輸入流中讀取數據位元組的數量,並寫入目的地緩衝區。
-(SIZE_T)(2 * pv) = 0 => CoTaskMemAlloc(0) 被召喚, 長度為0的緩衝區會被分配
-(ULONG)( 2 * pv – 2) = 0xfffffffe => IStream_Read(pstm, , 0xfffffffe) 被召喚,0xfffffffe的長度被寫入 到長度為o 的緩衝區
此處細節引我們得出以下結論:未打補丁的StructuredQuery.dll版本中,有一個整數的溢出漏洞,可以引到緩衝區溢出,讓攻擊者在漏洞系統上運行任意代碼。
這是我們在下一步中要測試的內容。
5.測試漏洞
為了這個測試,我們創建了一個概念驗證(PoC)win32控制台程序(structured_query_tests.cpp)以及一個惡意輸入文件(poc.dat)。
源代碼和內容截屏如下:
Structured_query_tests.cpp
PoC malicious input file
Structured_query_tests.cpp包含my_ReadPWSTR()功能,一個StructuredQuery.dll中未打補丁的ReadPWSTR()版本。
Poc.dat文件包含4個起始位元組,由IStream_Read (line 31)首次召喚讀取,並保存為pv變數,隨後用於再次召喚IStream_Read,觸發漏洞(留意小端位元組順序)。
在運行structured_query_tests.exe後,我們的猜想得到確認。以下是我們的WinDbg:
所以,再次從poc.dat文件中召喚IStream_Read() (line 37) read 0x80000000 bytes,並寫入長度為0 的分配緩衝區中,過度寫入後續內存塊,得出一個堆緩衝區溢出。
結論和未來工作
這個漏洞被微軟發布的Windows安全升級補丁標記為關鍵(CVE-2018-0825),類型為堆緩衝區溢出,是初始整數溢出。
這是由於變數類型的不恰當使用造成的。堆緩衝區溢出漏洞可被利用,故而攻擊者可能會在漏洞機器上通過確定合時的攻擊向量,運行任意代碼。
在Win 10系統中運行進程中快速搜索,使用Process Explorer確定將近20種進程可撬動StructuredQuery.dll,包括但不限於:OUTLOOK.exe, EXCEL.exe, explorer.exe, chrome.exe。
TAG:MottoIN |