作者:曹 磊(@iamelli0t)/ 深信服南研安全研究團隊
原文鏈接:https://mp.weixin.qq.com/s/sFWUK4HwctLRgnLEIvUBuw

CVE-2021-1732是今年二月份被披露的蔓靈花(BITTER)APT組織在某次攻擊行動中使用的0Day漏洞【1】【2】【3】。該漏洞利用Windows操作系統win32k內核模塊一處用戶態回調機會,破壞函數正常執行流程,造成窗口對象擴展數據的屬性設置錯誤,最終導致內核空間的內存越界讀寫。當受影響版本的Windows操作系統用戶執行攻擊者構造的利用樣本時,將會觸發該漏洞,造成本地權限提升【4】。

1. 漏洞原理分析

CVE-2021-1732漏洞形成的根本原因是:

Windows窗口創建(CreateWindowEx)過程中,當遇到窗口對象tagWND有擴展數據時(tagWND.cbwndExtra != 0),會通過nt!KeUserModeCallback回調機制調用用戶態ntdll!_PEB.kernelCallbackTable(offset+0x58)里的函數:user32!_xxxClientAllocWindowClassExtraBytes,從而在用戶態通過系統堆分配器申請(RtlAllocateHeap)擴展數據的內存。通過在用戶態hook user32!_xxxClientAllocWindowClassExtraBytes函數,并在hook函數中手動修改窗口對象擴展數據的屬性,可以破壞內核態為窗口對象擴展數據申請內存的原子操作,最終實現基于窗口對象擴展數據內存的越界讀寫能力。

Windows窗口創建(CreateWindowEx)過程的正常流程如下圖(部分):

通過上圖可以知道:當窗口的擴展數據大小tagWND.cbWndExtra不為0時,win32kfull!xxxCreateWindowEx 內部通過內核回調機制調用用戶態user32!_xxxClientAllocWindowClassExtraBytes函數,在用戶空間申請窗口對象擴展數據所需內存,最終將指針返回給窗口對象的tagWND.pExtraBytes屬性:

內核窗口對象tagWND的擴展數據有兩種保存方式:

1)保存于用戶態系統堆:即上圖所示的正常流程,用戶態系統堆申請的擴展數據內存指針直接保存于tagWND.pExtraBytes。

基于用戶態系統堆模式的一個tagWND內存布局如下圖所示:

2)保存于內核態桌面堆:函數NtUserConsoleControl調用會通過DesktopAlloc在內核態桌面堆分配內存,計算分配的擴展數據內存地址到桌面堆起始地址的偏移,保存在tagWND.pExtraBytes中,并修改tagWND.extraFlag |= 0x800:

基于內核態桌面堆偏移模式的一個tagWND內存布局如下圖所示:

因此可以通過hook回調user32!_xxxClientAllocWindowClassExtraBytes,在回調期間手動調用NtUserConsoleControl修改tagWND的擴展數據保存方式。然后在回調返回前手動調用ntdll!NtCallbackReturn:

通過ntdll!NtCallbackReturn返回用戶態可控offset值至tagWND.pExtraBytes,最終實現基于內核態桌面堆起始地址的可控offset越界讀寫能力。

修改后可以觸發漏洞的流程如下:

根據上面修改的流程圖,漏洞觸發的關鍵步驟如下:

1)修改PEB.kernelCallbackTable中user32!_xxxClientAllocWindowClassExtraBytes函數指針為自定義hook函數。

2)創建一些普通窗口對象,通過user32!HMValidateHandle泄漏這些tagWND內核對象在用戶態映射的內存地址。

3)釋放2)中創建的部分普通窗口對象,再次創建指定tagWND.cbwndExtra大小的窗口對象hwndMagic。此時該窗口對象有一定幾率使用之前釋放的窗口對象內存。因此在自定義hook函數中搜索之前泄漏的窗口對象用戶態映射內存地址,通過比較tagWND.cbwndExtra,就可以在CreateWindowEx返回前找到hwndMagic。

4)hook函數中調用NtUserConsoleControl修改hwndMagic的extraFlag |= 0x800。

5)hook函數中調用NtCallbackReturn將偽造offset賦值給hwndMagic的pExtraBytes。

6)調用SetWindowLong,向內核態桌面堆起始地址+指定offset越界寫入數據。

hook函數一種實現如下:

BSOD現場堆棧情況:

2. 漏洞利用分析

由漏洞原理分析部分知道:

通過該漏洞,可以獲得”一次修改基于內核態桌面堆起始地址+指定offset地址數據的機會“。對于內核態的漏洞,攻擊目標一般是獲得system權限,一種常用方法為:

1)利用漏洞獲得內核態任意地址讀寫權限

2)泄漏內核對象地址,通過EPROCESS鏈查找system進程

3)拷貝system進程token至本進程,完成提權工作

這里的難點為1):即如何利用”一次修改基于內核態桌面堆起始地址+指定offset地址數據的機會“,實現內核態任意地址讀寫。一種利用思路如圖所示:

1)首先利用漏洞,tagWNDMagic的附加數據(wndMagic_extra_bytes)的offset可控,可以通過SetWindowLong實現從桌面堆基址+可控offset的指定地址數據修改。

2)利用漏洞能力修改tagWNDMagic.pExtraBytes為tagWND0對象的offset (tagWND0的offset 由tagWND0+0x8獲得),調用SetWindowLong修改tagWND0.cbWndExtra = 0x0fffffff,從而獲得一個可越界讀寫的tagWND0.pExtraBytes。

3)計算tagWND0.pExtraBytes到tagWND1的offset,利用2)中獲得的可越界讀寫的tagWND0.pExtraBytes,調用SetWindowLongPtr修改tagWND1的spMenu指向偽造的spMenu,從而借助偽造的spMenu和GetMenuBarInfo實現任意地址讀能力。

GetMenuBarInfo讀取指定地址數據的邏輯如下,讀取的16字節數據被保存在MENUBARINFO.rcBar結構體中:

4)利用3)中獲得的可越界讀寫的tagWND0.pExtraBytes,修改tagWND1.pExtraBytes到指定地址,借助tagWND1的SetWindowLongPtr,獲得任意地址寫入能力。

5)獲得任意地址讀寫權限后,需要泄漏一個桌面堆上的內核對象地址來定位EPROCESS,這里步驟3)中為tagWND1設置偽造spMenu時SetWindowLongPtr返回值就是原spMenu的內核地址,可以直接利用。最后通過遍歷EPROCESS鏈查找system進程,并拷貝system進程token至本進程完成提權,此類方法比較常見,不再詳述。

最終完整的提權演示:

3. 參考文獻

[1] https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-1732
[2] https://ti.dbappsecurity.com.cn/blog/index.php/2021/02/10/windows-kernel-zero-day-exploit-is-used-by-bitter-apt-in-targeted-attack-cn/
[3] https://www.virustotal.com/gui/file/914b6125f6e39168805fdf57be61cf20dd11acd708d7db7fa37ff75bf1abfc29/detection
[4] https://en.wikipedia.org/wiki/Privilege_escalation

4. 團隊簡介

深信服南研安全研究團隊專注于高級威脅攻擊,在野漏洞利用追蹤、研究、檢測,攻防對抗等方向的研究工作。團隊成員曾在Windows,MacOS/iOS,Linux/Android等主流操作系統中發現了上百個安全漏洞,在BlackHat USA、BlackHat Europe、BlackHat Asia、HITB、Microsoft BlueHat、CodeBlue、HITCON、Virus Bulletin、Pacsec、看雪SDC、Freebuf CIS等國內外知名安全會議上發表過演講和論文。

如果你對以下技術內容感興趣,希望和高手切磋共事,趕緊發簡歷過來吧(郵箱caolei@sangfor.com.cn 工作地點:南京):
[APT攻擊溯源] 惡意代碼分析,威脅情報研究,APT溯源分析
[檢測引擎研發] EDR、XDR等檢測引擎研發
[攻防對抗技術] 紅藍對抗,ATT&CK技術研究,檢測規則編寫
[漏洞挖掘與利用] 在野漏洞利用研究,漏洞挖掘
[云原生安全] 云原生安全技術研究和產品研發
[MacOS安全] macOS安全產品核心模塊開發,macOS沙箱、EDP、EDR、DLP等安全產品開發
[大數據安全] 研發基于大數據技術的下一代安全產品


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1574/