Windows遠程桌面服務的遠程代碼執行漏洞(CVE-2019-1182)分析

2019年8月14日微軟官方發布安全補丁,修復了兩個Windows遠程桌面服務的遠程代碼執行漏洞CVE-2019-1181CVE-2019-1182,這兩個漏洞影響了幾乎所有目前受支持的Windows系統。此漏洞是預身份驗證且無需用戶交互,這就意味著這個漏洞可以通過網絡蠕蟲的方式被利用。

0×00 漏洞背景

019年8月14日微軟官方發布安全補丁,修復了兩個Windows遠程桌面服務的遠程代碼執行漏洞CVE-2019-1181/CVE-2019-1182,這兩個漏洞影響了幾乎所有目前受支持的Windows系統。此漏洞是預身份驗證且無需用戶交互,這就意味著這個漏洞可以通過網絡蠕蟲的方式被利用。利用此漏洞的任何惡意軟件都可能從被感染的計算機傳播到其他易受攻擊的計算機,與2019年5月14日修補的遠程桌面服務的遠程代碼執行漏洞CVE-2019-0708和2017年WannaCry惡意軟件的傳播方式類似。

0×01 分析環境

系統版本:Windows10 1903

補丁:windows10.0-kb4512508-x64_1893edc9a11d760be11e49d2500170ceee8026d7

0×02 成因分析

分別提取補丁前和補丁后RDS(Remote Desktop Service)進程相關bin文件及相關驅動模塊,經過ida和bindiff分析后定位到rdpbase.dll。該模塊改動很少(只有一處函數差異),可以很快定位到問題函數,如下圖所示。    

T-1.jpg

分析差異函數DecompressUnchopper::Decompress發現存在一處整型溢出漏洞

T-2.jpg

上圖左邊是patch之后的代碼,右邊是patch之前的代碼,可以看到pcach之前指令eax+0×2000作為函數new的參數使用,patch后增加了對size的校驗,會判斷edx+0×2000是否大于edx,什么情況下一個值加上0×2000會大于之前的值呢?對于無符號整數來說當0xffffe000<size<0xffffffff時,size+0×2000將位于(0,0×2000)這個區間,size>size+0×2000.補丁后的反編譯代碼如下

T-3.jpg

patch的思路很簡單,當size>size+0×2000時,new(-1)后續邏輯函數直接return。

下面我們根據DecompressUnchopper::Decompress的邏輯梳理一下該漏洞可能的利用思路。

T-4.jpg

如上圖所示,可以看到函數尾部調用了memcpy,第一個參數dest指向的內存為前面new分配的內存空間。如果我們把decompressedSize設置為[0xffffe000,0xffffffff]的一個值,當加上0×2000后decompressedSize小于原值,此時如果buff還是原來的大小,會導致memcpy的操作覆蓋掉dest后面buff-(decompressedSize+0×2000)個字節,如果后面的地址空間保存有虛表指針之類的地址則可以導致控制流劫持。

0×03 poc構造

以上的分析基于對相關模塊的逆向分析及靠經驗猜測,為了驗證思路是否正確首先需要能夠有觸達漏洞函數的rdp包。下面的敘述基于對CVE-2019-0708 poc的理解以及微軟官方提供的rdp協議文檔。

首先看一下微軟的官方公告[1]:

T-5.jpg

從公告的描述來看這個漏洞跟CVE-2019-0708類似,都可以造成蠕蟲傳播的效果,所以也是不需要進行登錄認證即可利用該漏洞遠程代碼執行,感覺大部分代碼可以復用所以決定在CVE-2019-0708的poc [2]基礎上構造CVE-2019-1182的poc。

通過研究CVE-2019-0708的poc和微軟官方文檔[3]可以了解到rdp協議的通信流程,如下圖所示:

T-6.png

至此找不到觸達漏洞函數的任何線索,思路還是要回到逆向漏洞函數周圍的處理邏輯上。交叉引用并沒有發現對DecompressUnchopper::Decompress的靜態調用,搜索一下DecompressUnchopper這個類相關的函數:

T-7-1.jpg

經過分析發現是DecompressRdp8__CreateInstance這個函數創建了DecompressUnchopper對象,繼續查看DecompressRdp8__CreateInstance沒有找到對此函數的靜態調用,發現這個函數是個導出函數,最后經過搜索發現該函數在rdpserverbase.dll中進行了導入,交叉引用發現有兩處調用

T-7.jpg

上圖中可以看到是在CRdpDynVC這個類的成員函數中進行了調用,因此猜測可能和rdp的dvc(Dynamic Virtual Channel)信道有關,關于dvc信道的詳細信息可參考微軟官方文檔[4]。通過查閱官方文檔初步定位到通過dvc信道發送加密數據可能會觸達漏洞函數。

dvc信道的建立流程如下:

(1) dvc init.

T-8.png

(2) dvc open

 T-9.png

(3) dvc send&recv data

T-9.png

dvc信道可分片傳輸超大數據(最大不超過2^32-1字節),并支持非加密和加密數據傳輸。

T-11.jpg

(4) dvc close

T-10.png

基于以上的研究,下面嘗試構造一個可觸達漏洞函數的dvc pdu。加密的dvc pdu結構如下圖所示,詳細信息參見官方文檔。

T-12.jpg

發送的數據包:

dvc_send = ( #pdu header"0300004002F08064000503EC70322A00000003000000" #1st byte cid length
"68" + channel_id[-2:] + "01110000"#data
"414141414141414141414141414141414141414141414141414141"
"414141414141414141414141414141414141414141414141414141"
"414141414141414141414141414141414141414141414141414141"
"414141414141414141414141414141414141414141414141414141"
"414141414141414141414141414141414141414141414141414141" 
"414141414141414141414141414141414141414141414141414141") tls.sendall(Packer(dvc_send).bin_unpack())

對DecompressUnchopper::Decompress下斷,運行腳本,觸發斷電,證明之前的猜測是正確的。

T-13.jpg

通過調試分析及參考官方文檔,構造如下數據包可導致crash:

dvc_send2 = ("0300004002F08064000503EC70322A00000003000000" "68" +channel_id[-2:] + "01E0FFFF" "e122550e0ffff080000002690ce0a2b9f6401070000002630d2b4fc0402") tls.sendall(Packer(dvc_send).bin_unpack()) 

崩潰現場:

T-14.jpg

調試分析導致crash的原因如下:DecompressedSize為0xffffe001,加0×2000之后為1,new(1)分配了一個字節的堆空間,memcpy多次像new分配的內存拷貝數據,導致數據一直向后覆蓋,圖中覆蓋到了RdpBoundsAccumulator對象,當執行clear操作時訪問無效地址造成memory corruption。

關于利用的一些思考:精準控制memcpy拷貝長度,覆蓋到某對象的虛表指針或其他可劫持控制流的內存單元,可導致任意代碼執行,需要考慮cfg等漏洞利用緩解措施的bypass。

References:

[1] https://msrc-blog.microsoft.com/2019/08/13/patch-new-wormable-vulnerabilities-in-remote-desktop-services-cve-2019-1181-1182/

[2] https://github.com/algo7/bluekeep_CVE-2019-0708_poc_to_exploit

[3] https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/5073f4ed-1e93-45e1-b039-6e30c385867c

[4] https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpedyc/3bd53020-9b64-4c9a-97fc-90a79e7e1e06

1

發表評論

已有 1 條評論

取消
Loading...

填寫個人信息

姓名
電話
郵箱
公司
行業
職位
css.php 什么app能玩二人麻将