微軟漏洞CVE-2017-11885分析與利用
根據微軟官網對CVE-2017-11885的描述,該漏洞幾乎可以通殺微軟的全版本作業系統,有關該漏洞的POC在exploit-db上於2018年5月份被披露,該POC僅僅針對windows server 2003進行了測試。
由於在相關描述中並沒有獲取到觸發該漏洞的原因,因此在獲取POC後,嘗試對該漏洞進行復現並分析。
POC的關鍵程式碼如下:
作者已經對該POC做了較為詳細的註釋,從stub的佈局以及註釋來看,第41行的stub資料可能會被傳入到CALL off_64389048[ECX*4]的ecx中,ecx如果是被控制的值,那麼基本上可以直接在目標系統執行任意程式碼了。接下來搭建一個windows server2003系統,並嘗試通過該POC觸發漏洞。
該漏洞僅當作業系統開啟了RRAS服務才會存在,在windows server2003中,通過管理工具->路由和遠端訪問進行配置,結果如下:
開啟了RRAS服務後,在另一臺主機執行POC,並抓包。發現使用了SMB協議進行資料傳輸,pcap包資料如下圖:
隨便開啟一個包,發現是SMB協議並且通過445埠傳送的資料,SMB協議後緊跟著DCERPC協議,對該協議的解釋如下:
還是相對古老的協議,而微軟的作業系統中的MSRPC協議是對DCERPC的一種實現,也算是第一代RPC協議。在這裡簡單介紹下RPC協議以及關鍵內容。
RPC 是指計算機 A 上的程序,呼叫另外一臺計算機 B 上的程序,其中 A 上的呼叫程序被掛起,而 B 上的被呼叫程序開始執行,當值返回給 A 時,A 程序繼續執行。A、B程序的互動過程如下圖:
RPC應用程式的開發基於C/S模式,在windows環境下開發RPC所要實現的內容有:
1.IDL檔案
2.ACF檔案(可選)
3.客戶端程式
4.服務端程式
IDL檔案是介面描述檔案,編寫該檔案所需的關鍵資訊包含程式註冊的uuid、函式呼叫介面以及引數的資料結構定義等。ACF檔案可用來建立一些相對複雜的資料結構,這裡不多關注。利用MIDL程式對IDL檔案進行編譯生成對應的客戶端和服務端所需的標頭檔案。客戶端程式和服務端程式包含著關鍵呼叫函式的主體程式。其整個模式類似於我們通常的WINAPI呼叫,如我們呼叫ReadFile函式時,通常需要傳遞一部分引數,並得到一個返回值,在RPC程式設計中客戶端程式負責引數的傳遞,服務端程式負責接收引數並執行相應的功能,隨後將資料返回,整個過程對於開發人員是透明的,只不過是跨計算機的呼叫。RPC開發具體可參考微軟的官方文件。
連結如下:https://docs.microsoft.com/en-us/windows/desktop/rpc/rpc-start-page。
這裡我們主要關注的內容包含RPC的協議傳輸方式、端點名稱、以及具體的程式介面呼叫。該POC利用到了impacket這個庫進行SMB以及rce協議的傳輸,POC中通過transport.DCERPCTransportFactory('ncacn_np:%s[\\pipe\\browser]' % target)進行遠端命名管道的連結,其中使用到的rpc協議為ncacn_np,通用的rpc協議如下:
而且,SMB作為rpc的底層通訊協議,一般都會同135、445這兩個埠進行通訊,一般的RPC 漏洞挖掘工具如spike等會通過特定埠查詢rpc服務的名稱資料庫來獲取一些關鍵資訊,如下:
但是本次漏洞中的服務端程式無法通過客戶端查詢來獲取資訊,原因可能是因為服務端在繫結端點時採用了動態繫結的方式,並且沒有將自身的相關資訊繫結到名稱服務中,將自身的資訊匯出到名稱服務一般需要呼叫如下函式:
這樣只有特定的程式才能夠訪問對應的服務端程式,一般的msrpc fuzz工具在獲取不到指定資訊,也不會對遠端服務進行fuzz,所以此類fuzz工具也難以挖掘到該型別的漏洞。
除了協議外,比較重要的一點就是遠端的端點了,該POC中用到了/pipe/browser這個遠端的命名管道,其實這個和RRAS協議中所規定的有點出入,在微軟的官方文件[MS-RRASM]中指出,如果需要同RRAS服務進行互動,應該使用/pipe/ROUTER這個命名管道。
當然漏洞的發現者之所以用這個命名管道當然有他的用意,這涉及到了另一方面的作業系統缺陷即MSRPC NULL sessions,在很早以前有人做過研究,可能在滲透中會用的多一些。還有一個相對重要的就是uuid,這代表著唯一的遠端服務端程式的標識,本次POC中對應的uuid為8f09f000-b7ed-11ce-bbd2-00001a181cad,同樣在官方文件中也有說明,該uuid對應著RRAS服務的應用程式。
接下來就開始對漏洞的除錯分析,通過在win7、winserver2003、winserver2008上進行測試,發現僅能在win server2003上觸發漏洞,win7尚沒有找到配置遠端路由的功能,儘管開啟了RRAS服務,但是無法觸發漏洞。
由於微軟不再維護win server2003的符號表,因此在除錯起來很難確定函式的關鍵的資訊,同時,由於使用的win server2003可能打了補丁,導致在傳送攻擊報文後,並沒有反彈shell,同時作業系統也沒有產生異常,當時懷疑該漏洞是否需要其它條件才能觸發,隨後查看了win server的事件日誌記錄,發現了一個appcrash記錄,點選進去檢視詳細資訊如下:
從圖中看出svchost.exe發生了崩潰,而svchost具有是管理、開啟服務的功能,因此猜測可能是RRAS服務在接收到攻擊報文後發生了異常,異常的模組是iptrmgr.dll,利用ida開啟該dll,同時跳轉到偏移為0x17436的地方檢視程式碼如下:
此處的程式碼和POC中提供的相對應,接下來利用除錯工具對RRAS服務進行除錯。由於在win server2003進行除錯,很多工具都無法使用,連最基本的windbg都無法使用,只能用最原始的OD來除錯,還有一個問題就是如何找到RRAS對應的svchost程式,因為系統會開啟多個svchost程式,在不考慮使用其他監控程式的情況下,可以使用tasklist /M iprtrmgr.dll來顯示當前載入了iprtrmgr.dll這個模組的svchost,基本可以確定該svchost同RRAS服務相對應,結果顯示如下:
接下來直接附加該程式,並在出現崩潰處的函式下斷點,觀察程式的狀態如下:
可以看出ecx的值來源於eax,而eax來自於第三個引數,在記憶體dump中可以看到這些是POC中構造的NDR(網路資料表示)資料,在MSRPC中,通過NDR引擎對引數格式進行編碼、解碼,比如客戶端希望傳遞一個結構體指標型別的引數,該引數在IDL檔案中被定義,在MIDL對IDL進行編譯的時候,會將該引數通過NDR引擎編碼轉換成為可以通過網路傳輸的資料格式,在服務端由NDR引擎進行解碼,並將解碼後的引數傳遞給服務端程式,整個過程對程式設計師是透明的。在POC中,作者通過構造特定的NDR資料作為服務端的引數進行漏洞利用,觀察0x64127058處的資料,發現該處儲存著函式列表,如下:
一共有0x23個函式,可以猜測服務端根據客戶端的呼叫號ecx值來確定下一步的函式呼叫,但是當傳入的ecx可以被控制時,那麼通過ROP技術可以控制整個程式的流程。
漏洞發現者通過在記憶體中找到包含著jmp eax這樣的gadgets來實現漏洞利用,但是由於應用程式的版本問題導致特定地址的程式碼並非預期,指向了一個不可讀的地址,因此這裡會產生一個訪問異常,使應用程式崩潰。
程式的呼叫棧當前無法正常顯示,但是檢視棧指標不難發現如下的函式呼叫:
這裡比較關鍵的是mprdim.dll,該dll存放著服務端的程式碼存根stub,利用ida的mIDA工具可以將RPC的IDL資料結構分析出來,通過對比發現win7和winserver上的程式碼基本類似,win7上也存在著本次的漏洞,由於win7上的dll可以獲取到符號,因此下面的所有程式碼都是對應的win7版本的,將win7下的mprdim.dll利用mIDA工具進行分析的結果如下:
可以看到觸發漏洞的函式為RMIBEntryGetFirst,該函式對應的呼叫號為0x1e(30),通過wireshark檢視RRAS協議的包格式也可以得到驗證:
接下來檢視該函式的一些關鍵RPC資料結構,如下:
該函式以及對應資料結構在微軟的官方文件有定義,如下:
從第二個引數開始,分別對應著我們構造的三個引數,第三個關鍵的引數為DIM_MIB_ENTRY_CONTAINER結構,當dwPid=10000時,該結構體指向 MIB_OPAQUE_QUERY,該結構體宣告如下:
在觸發漏洞的函式中,ecx代表著dwVarID,而dwVarID對應著函式的編號,微軟的解釋如下:
在ida中體現如下:
通過ida檢視該函式的整個實現發現,僅僅在開始對傳入資料中的dwPid進行檢測,而並沒有對引數範圍進行嚴格校驗,導致其最終指向了rop gadgets的地址。
在漏洞觸發的地方檢視關鍵的上下文資訊,發現eax指向了使用者傳入的引數的緩衝區,而該記憶體的屬性是RWE(可讀可寫可執行),簡直為漏洞利用提供了完美的環境,不需要通過ROP來繞過DEP等防護技術,該漏洞更像是一個後門。
當然存在漏洞的也不只這一處函式,檢視對函式表的引用可以發現共有三處,其執行邏輯基本類似,只要更改下函式呼叫號,同樣可以觸發。
前面提到過漏洞使用了/pipe/browser這個命名管道進行通訊,該命名管道在winxp 、win server2003預設開啟,並且是空會話格式的,意味著匿名的使用者也可以進行訪問,無需使用者名稱、密碼,但是在win server2008上,微軟關閉了大部分的命名管道,因此即便開啟了RRAS服務,前期的通訊尚無法建立,該漏洞自然無法成功利用,返回結果如下:
利用pipelist程式檢視當前開啟的命名管道,結果如下:
但是全部無法通過遠端訪問,結果如下:
所以,如果需要成功利用該漏洞,必須開啟一個空會話的命名管道,啟用方式如下:
這樣就可以通過POC對win server 2008進行攻擊了,而且最重要的是除錯起來相對更方便點,可以使用windbg並且載入符號進行除錯。
微軟目前已經對該程式打了補丁,打補丁的方式是在對引數的範圍作了校驗,如下: