標題:Windows RDP的RCE漏洞分析和復現(CVE-2019-0708)

taibeihacker

Moderator

0x00 漏洞描述​

Windows系列服務器於2019年5月15號,被爆出高危漏洞,該漏洞影響範圍較廣如:windows2003、windows2008、windows2008 R2、windows xp系統都會遭到攻擊,該服務器漏洞利用方式是通過遠程桌面端口3389,RDP協議進行攻擊的。這個漏洞是今年來說危害嚴重性最大的漏洞,跟之前的勒索,永恆之藍病毒差不多。 CVE-2019-0708漏洞是通過檢查用戶的身份認證,導致可以繞過認證,不用任何的交互,直接通過rdp協議進行連接發送惡意代碼執行命令到服務器中去。如果被攻擊者利用,會導致服務器入侵,中病毒,像WannaCry 永恆之藍漏洞一樣大規模的感染。 2019年9月7日晚上凌晨1點左右,metaspolit更新了漏洞利用程序
在2019年5月,微軟發布了針對遠程代碼執行漏洞CVE-2019-0708的補丁更新,該漏洞也稱為“BlueKeep”,漏洞存在於遠程桌面服務(RDS)的代碼中。此漏洞是預身份驗證,無需用戶交互,因此具有潛在武器化蠕蟲性性漏洞利用的危險。如果成功利用此漏洞,則可以使用“系統”權限執行任意代碼。 Microsoft安全響應中心的建議表明這個漏洞也可能會成為一種蠕蟲攻擊行為,類似於Wannacry和EsteemAudit等攻擊行為。由於此漏洞的嚴重性及其對用戶的潛在影響,微軟採取了罕見的預警步驟,為不再受支持的Windows XP操作系統發布補丁,以保護Windows用戶。

0x01 漏洞影响​

該漏洞影響舊版本的Windows系統,包括:Windows 7、Windows Server 2008 R2、Windows Server 2008、Windows 2003、Windows XP。 Windows 8和Windows 10及之後版本不受此漏洞影響。

0x02 cve_2019_0708_bluekeep_rce.rb 介绍​

此PR為CVE-2019-0708(又名BlueKeep)添加了一個漏洞利用模塊,該模塊通過RDP利用遠程Windows內核釋放後使用漏洞。 rdp termdd.sys驅動程序未正確處理綁定到僅限內部的通道ms_t120,從而允許格式錯誤的斷開連接提供程序指示消息導致釋放後被使用。利用可控制的數據和遠程非分頁面池堆噴射,使用空閒信道的間接調用小工具來實現任意代碼執行。
這個模塊最初由@zerosum0x0和@ryhanson開發,然後由@oj、@zerosteiner、@rickoates、@wvu-r7、@bwatters-r7、@wchen-r7、@tsellers-r7、@todb-r7和其他人進一步開發。為了利用metasploit中的rdp和其他庫增強功能,該模塊從python外部模塊移植到本機ruby模塊。果您希望檢查並將其與當前實現進行比較,則原始Python模塊位於提交歷史記錄中。
該模塊當前以64位版本的Windows 7和Windows Server 2008 R2為目標。對於Windows Server 2008 R2,需要修改註冊表項以啟用通過rdpsnd通道進行堆噴射,但仍有其他可能使用在所有Windows操作系統上默認啟用的備用通道。
由於用戶需要提供額外的目標信息或有使目標主機崩潰的風險,該模塊目前被列為手動模塊。該模塊實現了一個默認的僅指向的目標選項,該選項只檢查易受攻擊的主機,並顯示有關特定目標操作系統的一些初始信息,但用戶需要根據輔助偵察指定更精確的目標或直到進一步改進模塊可以在運行時更準確地確定目標內核內存佈局。
有針對沒有打補丁的,裸機、VirtualBox、VMWare和Hyper-V的特定目標,儘管目標環境中可能還有其他變量,這些變量會額外轉移基礎地址以進行修飾。

0x03 漏洞分析​

1. PDU​

根據MS-RDPBCGR(遠程桌面協議:連接和遠程處理)文檔,位圖緩存PDU的全名是TS_BITMAPCACHE_PERSISTENT_LIST_PDU,密鑰列表PDU數據被嵌入在永久密鑰列表PDU中。永久密鑰列表PDU是在客戶端從客戶端發送到服務器的RDP連接序列PDU
RDP連接序列的連接完成階段,如圖1所示。
0y1njyrpot322527.png

圖1.遠程桌面協議(RDP)連接順序
永久密鑰列表PDU報頭是通用RDP PDU報頭,其構造如下,如圖2所示:tpktHeader(4字節)+ x224Data(3字節)+ mcsSDrq(變量)+ securityHeader(變量)。
nlaw2oavjfn22528.png

圖2.客戶端持久密鑰列表PDU
根據MS-RDPBCGR文檔,TS_BITMAPCACHE_PERSISTENT_LIST_PDU是一個結構,其中包含從先前會話中發送的高速緩存位圖中保存的高速緩存位圖密鑰列表。如圖3所示。
0ygiznczwra22529.png

圖3.持久密鑰列表PDU數據(BITMAPCACHE PERSISTENT LIST PDU)
根據設計,位圖緩存PDU用於RDP客戶端通知服務器它具有與密鑰相關聯的位圖的本地副本,這表明服務器不需要將位圖重新發送到客戶端。基於MS-RDPBCGR文檔,Bitmap PDU有四個特徵:
RDP服務器將分配內核池來存儲緩存的位圖鍵。
RDP服務器分配的內核池大小可以通過結構中的“WORD值”numEntriesCache X字段來控制,而BITMAPCACHE PERSISTENT中的totalEntriesCache X是RDP客戶端的LIST結構。
位圖緩存PDU可以合法地多次發送,因為位圖密鑰可以在多個持久密鑰列表PDU中發送,每個PDU使用bBitMask字段中的標記來標記。
位圖鍵的數量限制為169。
基於BITMAPCACHE PERSISTENT LIST PDU的這四個特性,如果可以繞過限制為169的位圖鍵數量,那麼就可以將任意數據寫入內核。

2.如何使用PDU将数据写入内核​

根據MS-RDPBCGR文檔,正常解密的BITMAPCACHE PERSISTENT LIST PDU如下所示:
f200-TS_SHARECONTROLHEADER:totalLength=0x00f2=242bytes1700-TS_SHARECONTROLHEADER:pduType=0x00170x0017=0x0010|0x0007=TS_PROTOCOL_VERSION|PDUTYPE_DATAPDUef03-TS_SHARECONTROLHEADER:pduSource=0x03ef=1007e a030100-TS_SHAREDATAHEADER:shareID=0x000103ea00-TS_SHAREDATAHEADER:pad101-TS_SHAREDATAHEADER:streamId=STREAM_LOW(1)0000-TS_SHAREDATAHEADER:uncompressedLength=02b-TS_SHAREDATAHEADER:pd uType2=PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST(43)00-TS_SHAREDATAHEADER:generalCompressedType=00000-TS_SHAREDATAHEADER:generalCompressedLength=00000-TS_BITMAPCACHE_PERSISTENT_LIST:numEntries[0]=00000-TS_B ITMAPCACHE_PERSISTENT_LIST:numEntries[1]=01900-TS_BITMAPCACHE_PERSISTENT_LIST:numEntries[2]=0x19=250000-TS_BITMAPCACHE_PERSISTENT_LIST:numEntries[3]=00000-TS_BITMAPCACHE_PERSISTENT_LIST:numEnt ries[4]=00000-TS_BITMAPCACHE_PERSISTENT_LIST:totalEntries[0]=00000-TS_BITMAPCACHE_PERSISTENT_LIST:totalEntries[1]=01900-TS_BITMAPCACHE_PERSISTENT_LIST:totalEntries[2]=0x19=250000-TS_BITMAPCACHE_PERSIST ENT_LIST:totalEntries[3]=00000-TS_BITMAPCACHE_PERSISTENT_LIST:totalEntries[4]=003-TS_BITMAPCACHE_PERSISTENT_LIST:bBitMask=0x030x03=0x01|0x02=PERSIST_FIRST_PDU|PERSIST_LAST_PDU00-TS_BITMAPCACHE_PERSISTE NT_LIST:Pad20000-TS_BITMAPCACHE_PERSISTENT_LIST:Pad3TS_BITMAPCACHE_PERSISTENT_LIST:entries:a31e5116-Cache2,Key0,Low32-bits(TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY:Key1)48292278-Cache2,Key0,Hi gh32-bits(TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY:Key2)61f7899c-Cache2,Key1,Low32-bits(TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY:Key1)cda966a8-Cache2,Key1,High32-bits(TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY:Key2)
在內核模塊RDPWD.sys中,函數例程ShareClass : SBC_HandlePersistentCacheList負責解析BITMAPCACHE PERSISTENT LIST PDU。當結構中的bBitMask字段被設置為位值0x01時,它指出當前PDU是PERSIST FIRST PDU。然後,SBC_HandlePersistentCacheList將調用WDLIBRT_MemAlloc來分配內核池(分配內核內存)以存儲持久位圖緩存鍵,如圖4所示。值0x00表示當前PDU是PERSIST MIDDLE PDU。值0x02表示當前PDU是PERSIST LAST PDU。解析PERSIST MIDDLE PDU和PERSIST LAST PDU時,SBC_HandlePersistentCacheList會將位圖緩存鍵複製到之前分配的內存中,如圖5所示。
gjuvdtqd0ds22530.png

圖4. SBC_HandlePersistentCacheList池分配和totalEntriesCacheLimit檢查
e513mvrf1te22531.png

圖5. SBC_HandlePersistentCacheList複製位圖緩存鍵
Windows 7 x86上的堆棧跟踪和SBC_HandlePersistentCacheList的TS_BITMAPCACHE_PERSISTENT_LIST結構的第二個參數如圖6和圖7所示。
tbdoklfb04r22532.png

圖6. SBC_HandlePersistentCacheList堆棧跟踪
025ffxyrcgu22533.png

圖7. TS_BITMAPCACHE_PERSISTENT_LIST結構作為SBC_HandlePersistentCacheList的第二個參數
如圖4所示,bitmapCacheListPoolLen=0xC *(總長度+4)和總長度=totalEntriesCache0 + totalEntriesCache1 + totalEntriesCache2 + totalEntriesCache3 + totalEntriesCache4。
基於此公式,我們可以設置“WORD值”totalEntriesCache X=0xffff,使bitmapCacheListPoolLen為最大值。但是,對於圖8中顯示的每個totalEntriesCache X,都有一個totalEntriesCacheLimit檢查.
totalEntriesCacheLimit X來自TS_BITMAPCACHE_CAPABILITYSET_REV2結構,該結構在通過RDPWD調用DCS_Init時在CAPAPI_LOAD_TS_BITMAPCACHE_CAPABILITYSET_REV2函數中啟動,如圖8所示。這將在解析確認PDU時組合在CAPAPI_COMBINE_TS_BITMAPCACHE_CAPABILITYSET_REV2函數中,如圖9所示。
nn50w3rprze22534.png

圖8. RDPWD! CAPAPI_LOAD_TS_BITMAPCACHE_CAPABILITYSET_REV2
3mzn54l4xuq22535.png

圖9. RDPWD! CAPAPI_COMBINE_TS_BITMAPCACHE_CAPABILITYSET_REV2
CAPAPI_COMBINE_TS_BITMAPCACHE_CAPABILITYSET_REV2將服務器啟動的NumCellCaches(0x03)和totalEntriesCacheLimit [0-4](0x258,0x258,0x10000,0x0,0x0)與客戶端請求NumCellCaches(0x03)和totalEntriesCache [0-4](0x80000258,0x80000258,0x8000fffc,0x0)組合在一起,0x0),如圖9中的edx和esi寄存器所示。
客戶端可以控制NumCellCaches和totalEntriesCache [0-4],如圖10所示,但它們不能通過服務器啟動的NumCellCaches(0x03)和totalEntriesCacheLimit [0-4] ](0x258,0x258,0x10000,0x0,0x0)如圖11所示。
vzguwdvbkdn22536.png

圖10. TS_BITMAPCACHE_CAPABILITYSET_REV2
ujtp5ujdqsu22537.png

圖11. CAPAPI_COMBINE_TS_BITMAPCACHE_CAPABILITYSET_REV2函數
有了這些信息,我們可以計算出最大bitmapCacheListPoolLen=0xC *(0x10000 +0x258 +0x258 + 4)=0xc3870,理論上可以控制內核池中的0x8 *(0x10000 +0x258 +0x258 + 4)=0x825a0字節數據,如圖所示在圖12中。
u3jpvpd3vbk22538.png

圖12.持久密鑰列表PDU內存轉儲
但是,觀察到並非所有數據都可以由位圖緩存列表池中的RDP客戶端按預期被控制。每個8字節受控數據之間存在4字節不受控制的數據(索引值),這對於shellcode存放是不太友好的。此外,0xc3870大小的內核池不能多次分配,因為持久密鑰列表PDU只能合法地發送一次。但是,仍然存在特定的統計特徵,即內核池將在相同的內存地址處分配。此外,在位圖緩存列表池分配之前總是有一個0x2b522c(在x86上)或0x2b5240(在x64上)內核大小的池,這對於堆分配非常有用,尤其是在x64上,如圖13所示。
1wiblvvqhes22539.png

圖13.持久密鑰列表PDU統計特性

3.刷新Rect PDU​

根據MS-RDPBCGR文檔,刷新PDU會使RDP客戶端請求服務器重新分配一個會話。該結構包括通用PDU頭和圖14中所示的refreshRectPduData(變量)。
pycus3pzflw22540.png

圖14.刷新Rect PDU數據
numberOfAreas字段是一個8位無符號整數,用於定義areasToRefresh字段中的包含Rectangle結構的數量。 areaToRefresh字段是TS_RECTANGLE16結構的數組,如圖15所示。
zwaxcspvivu22541.png

圖15.包含Rectangle(TS_RECTANGLE16)
Refresh Rect PDU通過一系列“Inclusive Rectangles”操作通知服務器,以使服務器重新分配一個會話。基於默認通道,通道ID為0x03ea(服務器通道ID)。連接序列完成後,如圖1所示,RDP服務器可以接收/解析刷新矩陣PDU,最重要的是,可以合法地多次發送。雖然對於TS_RECTANGLE16結構僅限於8個字節,意味著RDP客戶端只能控制8個字節,但仍然可以將任意數據寫入內核。

4.使用Refresh Rect PDU将数据写入内核​

正常解密的Refresh Rect PDU如圖16所示。
f3r3lavdpyn22542.png
 
返回
上方