您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關如何進行微軟RDP服務高危UAF漏洞分析,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
CVE-2019-0708已經披露了,下面將主要圍繞以下幾個方面介紹該漏洞。
1、 經過分析驗證該漏洞是一個UAF漏洞,引發UAF漏洞的指針是由何時創建以及為何該指針在Free之后又被使用,是本文重點關注的地方。
2、 該漏洞屬于RDP協議實現方面的漏洞,文中會列舉與該漏洞相關的RDP協議知識。
遠程桌面協議(RDP, RemoteDesktop Protocol)是一個多通道(multi-channel)的協議。
RDP協議也是C/S網絡結構,雙方通過TCP連接進行通信,基本也是基于請求/響應這樣的數據交換模式,這里貼一張來自微軟發布的RDP協議時序圖,該圖詳細描述了RDP連接中請求及響應的順序及過程。
該文檔([MS-RDPBCGR].pdf)地址如下:https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/5073f4ed-1e93-45e1-b039-6e30c385867c。
文中不介紹通訊細節,有興趣的讀者可以自行閱讀該文檔。
靜態虛擬通道允許RDP Client和RDP Server通過主RDP數據連接通信。虛擬通道數據是特定于應用程序的,對RDP不透明。連接時最多可以創建31個靜態虛擬通道。RDP Client在連接序列的Basic Settings Exchange階段請求并確認所需虛擬通道列表,并在ChannelConnection階段進行信道的連接。
每個虛擬通道充當獨立的數據流。RDP Client和RDP Server檢查在每個虛擬通道上接收的數據,并將數據流路由到適當的處理函數以進行進一步處理。
已確認的是,CVE-2019-0708為UAF漏洞,眾所周知UAF漏洞主要是由于對象指針在釋放后再次被使用而引發的安全問題。那么在這一部分內容中,我將描述引發UAF漏洞的指針是由何時創建以及為何該指針在Free之后又被使用。
1) RDP連接建立,RDP Server 默認調用IcaCreateChannel()創建MS_T120靜態虛擬信道,并綁定到0x1F信道號,此時是該信道第一次綁定。
2) RDP Client 在通訊的Channel Connecttion階段告知 RDPServer 綁定名稱為“MS_T120”的信道到指定信道,此時Server使用IcaFindChannelByName()函數搜索到默認創建的MS_T120信道,將該信道對象綁定到用戶指定的信道號上。此時是MS_T120信道第二次綁定。
3) 至此,MS_T120信道已經完成2次綁定。隨后RDP Client 告知RDP Server斷開第二次綁定的信道,該操作會引發RDP Server 調用IcaFreeChannel()釋放該信道并釋放該對象占用的空間。
4) 隨后RDP Client 將通知RDP Server關閉RDP連接,此操作會引發Server調用SingalBrokenConnection()函數釋放信道號0x1F的MS_T120信道對象。由于該對象空間已經釋放過,這里再次調用IcaFreeChannel()函數執行清理操作,其中ExDeleteResourceLite()會引用該對象的成員數據而觸發UAF漏洞。
下圖是漏洞補丁修復前后對比圖:
關鍵的修改是針對_IcaBindChannel()函數的調用前增加了一個條件判斷,判斷的內容是stricmp() 返回值,也就是字符串是否相等。
而以字面意思解讀icaFindChannelByName(),就是以名字查找信道。下圖為該函數的實現,通過遍歷列表,可以確定的是信道對象中偏移0x94的位置就是信道名稱。
回過頭來看漏洞補丁的代碼,實際上打過補丁后,在調用icaBindChannel()函數的之前,也是進行信道名稱的判定,當信道名稱為”MS_T120” 的時候,后續調用icaBindChannel()的第三個參數,強制改為0x1F。
這里看一看icaBindChannel()函數的實現,關鍵在第12行的代碼中,會將傳入該函數參數1的信道指針,寫入一個內存地址中。顯而易見的是,寫入的地方是通過參數2及參數3計算得到。
實際上這個函數就是漏洞的關鍵,至于為什么關鍵,我們后面再談。首先先介紹一下,引起UAF的對象指針是何時創建的。
早在前文已經介紹過, RDP協議定義靜態虛擬信道,而名稱為MS_T120的信道就是其中一個。MS_T120在RDP協議建立之初,就會由RDP服務端主動創建,本次漏洞引起UAF的對象指針就是MS_T120信道。termdd!icaCreateChannel()函數用于創建信道,在該函數設置斷點,使用微軟遠程桌面連接工具連接并觀察一下該信道建立的過程。
通過分析該函數代碼可知,參數2偏移0xC的位置為信道名稱。建立RDP連接,WinDbg停在IcaCreateChannel()處,其參數中的名稱正是MS_T120
進一步跟蹤該函數,進入了關鍵函數_IcaAllocateChannel(),如下圖,該函數首先調用ExAllocatePoolWithTag()申請空間,之后就是對象成員初始化工作。
值得注意的是,在初始化完部分成員變量之后,又調用了icaBindChannel(), 在windbg中實時跟蹤該調用:
可以發現,此時的參數3為0x1F,此時調用icaBindChannel()將新創建的MS_T120信道放入數組下標0x1F的位置。
也就是說,MS_T120信道對象指針在RDP 連接創建的時候就會建立,并立即綁定到0x1F信道號中。這是該指針創建的地方,在這里還將該信道綁定到了0x1F信道號中。
此時回過頭來看微軟補丁修復的地方,未修復之前,程序代碼在調用icaFindChannelByName()之后,緊接著調用icaBindChannel()將信道綁定到指定的信道號中。
在修復之后,會判斷信道是否為MS_T120,如果是,將綁定的信道號重定向為0x1F,而不是用戶指定的信道號。實際上UAF漏洞的關鍵就在這里,我們知道MS_T120信道在連接建立之初就已經和0x1F綁定,此時如果再次將MS_T120和另一個信道號綁定,在關鍵數組中就會存在2個指針值,也就是綁定了2次。
目前在Github上(https://github.com/n1xbyte/CVE-2019-0708/ )有一份可以UAF導致藍屏的POC,下面跟蹤驗證一下。
該POC使用Python編寫,在ubuntu上安裝python環境即可運行該POC
該POC通過發送MCS Connect Initial請求,觸發RDP 服務端中icaBindVirtualChannel()中引發UAF漏洞的代碼。
繼續單步走觀察調用_IcaBindChannel()時的信道號,下圖可見此時信道號為3.此時會將MS_T120信道與POC中指定的3號信道號綁定。
之后該POC會發送數據包通知RDP服務端斷開3號信道的連接,這將會引發服務端調用icaFreeChannel(), 該函數會調用ExFreePoolWithTag()釋放空間。
之后POC通知RDP Sever關閉RDP連接,而在關閉連接的時候,會觸發默認的位于下標0x1F的信道釋放操作,如下圖所示(圖片為多次調試所截取,其中關鍵指針值不同不要引起疑惑):
這里繼續單步走,可以發現觸發了內核異常。
F5繼續運行系統,引發藍了。顯示如下
經過智能分析后如下,核心原因則是0x83e9b362處的代碼對ecx保存的內存地址進行了寫,可以看到的是,當時的ecx為0,根據異常類型表示,當前IRQL無法對0地址進行讀寫。
仔細看下2張圖可以發現,ecx 來源于edi,而edi 是icaFreeChannel()的傳入參數,也就是待釋放的信道對象指針。已釋放的指針被再次引用,所以導致了漏洞。
這里引用的來源即icaFreeChannel()中調用的ExDeleteResouceLite(),在釋放信道對象之前,會使用該對象的一些數據。
通過以上的分析可知,MS_T120信道被綁定兩次(一次由RDPserver創建并綁定,第二次由我們發送數據包綁定)。由于信道綁定在兩個不同的ID下,我們得到兩個獨立的引用。
當使用其中的一個引用來關閉信道時,將刪除該引用,信道對象也將釋放。但是,另一個引用仍然存在。如果我們可以在第一次釋放信道對象空間之后,通過內核POOL噴射,獲得在該信道對象填充自定義數據的能力,在第二次調用IcaFreeChannel()進行空間釋放時,由于該函數會引用已被控制的內核對象,就有機會造成讀寫任意內核地址進而達到任意代碼執行的目的。
以上就是如何進行微軟RDP服務高危UAF漏洞分析,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。