一、前言
在研究繞過UAC(用戶賬戶控制)的新型技術(shù)時,我發(fā)現(xiàn)了一種新的繞過方法。雖然微軟并不認為UAC屬于安全邊界范疇,但我們依然將這個問題反饋給微軟,也愿意在此處與大家分享。我們已經(jīng)在Windows 10 Build 17134上測試過這種方法。在深入分析繞過方法之前,本文首先將簡要回顧一下UAC的背景知識,以便幫助大家了解UAC的內(nèi)部工作原理。
二、背景知識
當(dāng)隸屬于Administrators組的用戶想執(zhí)行需要高權(quán)限的某個進程時,系統(tǒng)就會彈出UAC提示窗口,確認用戶提升進程權(quán)限。然而,Windows系統(tǒng)中并非所有的特權(quán)可執(zhí)行程序都會彈出UAC窗口,某些例外情況下并不會彈出該窗口,而會“自動提升”目標(biāo)可執(zhí)行文件的權(quán)限,這樣就能繞過UAC機制(許多人肯定會感到非常驚訝)。
系統(tǒng)對這類受信任的可執(zhí)行文件做了其他一些安全檢查,以確保這些文件的確可信,不會被攻擊者濫用。之前的UAC繞過技術(shù)中廣泛利用了這種方法,本文的利用思路也不例外。然而,為了成功繞過UAC,我們需要在攻擊過程中跳過一些“坑”。如果我們的可執(zhí)行文件想實現(xiàn)“自動提權(quán)”,就必須遵循某些強制性條件。為了分析整個過程,這里我將給大家展示appinfo.dll(處理權(quán)限提升的AIS服務(wù),屬于UAC的核心組件之一)中的一些反匯編代碼片段。
條件1:autoElevate為True
當(dāng)出現(xiàn)程序權(quán)限提升情況時,系統(tǒng)就會對AIS(appinfo.dll)執(zhí)行RPC調(diào)用,將目標(biāo)可執(zhí)行文件的路徑作為調(diào)用參數(shù)。隨后,該服務(wù)會映射目標(biāo)可執(zhí)行文件的內(nèi)容以便后續(xù)讀取,系統(tǒng)會嘗試讀取可執(zhí)行文件的manifest信息,解析autoElevate字段(如果該字段存在)的值。

圖1. 讀取可執(zhí)行文件的Manifest信息解析可能存在的autoElevate值
如果該字段存在并且值為True,那么系統(tǒng)會認為這是一個可以自動提升權(quán)限的可執(zhí)行文件,隨后執(zhí)行權(quán)限提升,繞過UAC提示框(前提是該文件已通過另一個限制條件,下文會提到這個問題)。然而,這種autoElevate規(guī)則依然存在一個例外情況。無論manifest的具體內(nèi)容是什么,如果文件名匹配某個白名單中的EXE名稱,系統(tǒng)也會將其當(dāng)成具備“自動提升權(quán)限的”可執(zhí)行文件。如下圖所示,代碼中在manifest檢查過程后有一個bsearch調(diào)用,檢查文件名是否匹配白名單可執(zhí)行文件名列表。如果文件名滿足條件,那么就會自動提升權(quán)限,無視manifest數(shù)據(jù)。

圖2. bsearch調(diào)用測試可執(zhí)行文件名是否匹配自動提升權(quán)限的exe文件名
硬編碼的白名單文件名部分列表如下:
cttunesvr.exe
inetmgr.exe
migsetup.exe
mmc.exe
oobe.exe
pkgmgr.exe
provisionshare.exe
provisionstorage.exe
spinstall.exe
winsat.exe’
條件2:經(jīng)過簽名
如果UAC請求所對應(yīng)的二進制文件已配置為“自動提升權(quán)限”,那么系統(tǒng)就會使用wintrust!WTGetSignatureInfo來檢查文件的簽名。這意味著攻擊者無法簡單地構(gòu)造manifest信息或者可執(zhí)行文件名來實現(xiàn)自動權(quán)限提升,因為攻擊者的文件很可能沒有經(jīng)過正確的簽名處理,并且很有可能無法滿足第3個條件(即從可信目錄中執(zhí)行)。
條件3:從可信目錄中執(zhí)行
實現(xiàn)自動權(quán)限提升的第3個條件:目標(biāo)可執(zhí)行文件位于“可信目錄”中,比如C:\Windows\System32。如圖3所示,AIS會檢查權(quán)限提升請求所對應(yīng)的文件路徑,在本例中,“可信目錄”為C:\Windows\System32。

圖3. 檢查可信路徑
既然本文的名字為“如何通過模擬可信目錄繞過UAC”,大家應(yīng)該能猜到我們下文的內(nèi)容了。
三、繞過UAC
在背景知識中我們提到過,如果滿足如下條件,則可以實現(xiàn)權(quán)限自動提升(UAC繞過):
1、配置為權(quán)限自動提升;
2、經(jīng)過正確簽名;
3、從可信目錄(C:\Windows\System32)中執(zhí)行。
在檢查可信目錄時,Appinfo.dll(AIS)會使用RtlPrefixUnicodeString這個API來檢查目標(biāo)可執(zhí)行文件路徑是否以C:\Windows\System32\作為前綴。這是非常可靠的檢查過程,因為系統(tǒng)會檢查目標(biāo)可執(zhí)行文件的標(biāo)準路徑。為了繞過這個檢查步驟,我構(gòu)造了一個目錄:C:\Windows \(請注意Windows后面跟著一個空格符)。當(dāng)然這個路徑并不能繞過RtlPrefixUnicodeString,并且由于Windows不允許在目錄名末尾附加一個空格符,因此這并不是一個有效的目錄名(或者至少不是一個“友好的”目錄名)。然而,如果我們使用CreateDirectory API,然后在待創(chuàng)建的目錄名前加上\\?\,那么我們就可以繞過系統(tǒng)的一些命名規(guī)則,將目錄創(chuàng)建請求直接發(fā)送給文件系統(tǒng)。

圖4. 調(diào)用API
這將導(dǎo)致系統(tǒng)中出現(xiàn)一個尷尬的目錄,能夠與真正的C:\Windows\目錄和諧共存(然而我們不能在Windows資源管理器中對這個目錄做任何操作)。

圖5. 目錄刪除請求無法成功,也無法通過重命名來刪除末尾的空格符
現(xiàn)在我們已經(jīng)創(chuàng)建了一個C:\Windows \目錄,我們可以在該目錄中創(chuàng)建一個system32目錄,然后將C:\Windows\System32目錄中經(jīng)過簽名的、能夠自動提升權(quán)限的可執(zhí)行應(yīng)用拷貝到該目錄中。這里我選擇拷貝winSAT.exe(這是位于自動提升權(quán)限白名單中的一個Windows可執(zhí)行文件)。當(dāng)我們嘗試運行C:\Windows \System32\winSAT.exe時,appinfo.dll在檢查可信目錄時會先調(diào)用如下API(如圖6所示)。這一點非常關(guān)鍵,這也是我們?yōu)槭裁茨芾@過UAC的原因所在。
圖6. API調(diào)用過程
當(dāng)請求權(quán)限提升過程將這個尷尬的目錄發(fā)送到AIS時,該路徑會傳遞給GetLongPathNameW函數(shù),該函數(shù)會將該路徑轉(zhuǎn)換回C:\Windows\System32\winSAT.exe(刪除了空格符)。非常完美,現(xiàn)在這個路徑已經(jīng)變成了可信目錄(可以通過RtlPrefixUnicodeString的檢查)。更加完美的是,當(dāng)完成可信目錄檢查后,后續(xù)檢查(以及最終的權(quán)限提升請求)依然會使用原始的文件名(帶有空格符)。這樣我們就能通過其他所有檢查,最終讓appinfo.dll執(zhí)行我們復(fù)制的winSAT.exe,自動提升權(quán)限(因為該文件已經(jīng)過正確簽名,并且處于自動提升權(quán)限的白名單中)。
為了通過這種方法真正執(zhí)行攻擊者的代碼,我將一個偽造的WINMM.dll(該dll會被winSAT.exe加載)釋放到了C:\Windows \System32\中,通過本地dll劫持技術(shù)執(zhí)行我們的代碼。完整的流程如下圖所示。

圖7. 完整利用過程
完整代碼可以訪問Github下載。
|