Matt Graeber (@mattifestation) 和我最近在研究Windows 10,我们发现了一个相当有趣的方法来绕过用户账户控制(User Account Control, UAC,详细内容可以参考这里)。现在已经存在几种公开的UAC绕过技术 ,其中大多数需要一个权限文件副本,使用IFileOperation COM对象或者WUSA提取来进行DLL拦截。你可以从这里(作者@hfiref0x)参考一些公开的绕过方法来深入研究一下。我们这次所使用的技术和以往的方法不同,我们提供了一个有效的替代方案,它并不依赖于权限文件副本或任何代码注入。
在Windows上调查加载的情况的一个常用技术是使用SysInternals Process Monitor来分析一个正在执行的进程的具体行为。理解了Windows 10上存在的一些默认任务调度程序和它们之间的通信行为之后,我们发现有一个名为“SilentCleanup”的任务调度程序被配置为对无权限用户可优先执行,但是是在高完整性级别下运行。为了弄清楚,我们简单把任务逐个查看了一遍,发现“在最高权限下运行”这一安全选项是在低等级用户账户(比如“users”)中检查的。
仔细查看procmon,我们发现实际的进程是由计划任务cleanmgr.exe启动的,自动提权是由于任务配置设置成了“在最高权限下执行”。
让我们更进一步探究。当程序cleanmgr.exe执行时,它会在地址“C:Users<username>AppDataLocalTemp”下创建一个使用GUID数值进行命名的新文件夹。
cleanmgr.exe创建了临时文件夹之后,它会复制多个DLL并连同“dismhost.exe”
一起放到新文件夹中:
在复制DismHost.exe和它的DLL文件到目录“C:Users<username>AppDataTemp<guid>”后,cleanmgr.exe从最新创建的路径下启动DismHost.exe作为一个高完整性级别的进程:
DismHost.exe从“C:Users<username>AppDataLocalTemp<guid>”中启动后,它开始以特定顺序从同一文件夹中加载DLL:
因为目前完整性级别为中等的用户有USER的%TEMP%目录的写权限,通过DismHost.exe劫持DLL并在一个高完整级别进程中执行代码已经可以实现。这就是大家所熟知的“BypassUAC”UAC绕过攻击。
因为现在的情况是一种竞争的状态,我们需要在DismHost.exe加载目标DLL之前把它替换掉。我们更加仔细地测试了整个过程,并发现“LogProvider.dll”是DismHost.exe加载的最后一个DLL,这给了我们一个劫持的最佳时机。有了这个信息,我们可以使用一个WMI(Windows Management Instrumentation)事件来监视“C:Users<username>AppDataLocalTemp<guid>”是否被创建,然后分配给WMI事件一个动作,通过复制我们的“恶意”DLL到 “C:Users<username>AppDataLocalTemp<guid>” 中并将其命名为“LogProvider.dll”,从而劫持 “LogProvider.dll” 。因为这一动作在dismhost.exe加载DLL之前发生,dismhost.exe就会加载我们的DLL而不是原来的那个。
一旦dismhost.exe加载了我们的DLL,它就会以高完整性级别加载,从而允许我们绕过UAC并获取高完整性级别进程的代码执行权限。
在随后的测试中我们发现,此方法不适用于标准user账户,因为cleanmgr.exe不会从%TEMP%中提取任何文件。当该程序在标准用户的低完整性或中等完整性级别下执行时,任务会在中等完整性级别运行,无法通过这个进行提权。
Matt Graeber (@mattifestation)写了一个很棒的 PowerShell验证脚本,用来注册一个WMI事件监视cleanmgr.exe是否创建GUID文件夹,一旦检测到,该脚本会复制特定DLL到GUID文件夹并名为“LogProvider.dll”。只要dismhost.exe加载了“LogProvider.dll”,我们就能保证它加载的是我们的恶意DLL而不是原来那个合法的,这样就实现了UAC的绕过并且给我们在高完整性权限下执行代码的权限。你可以通过以下链接查看脚本码https://gist.github.com/mattifestation/b4072a066574caccfa07fcf723952d54
如果你想检验一下这个方法,你只需要这个验证脚本和一个拥有Dllmain标准输出的DLL即可。你可以自己创建一个DLL,或者使用一个简单的MessageBox
:https://github.com/enigma0x3/MessageBox。
这个方法不同于其他公开的方法,它有以下几个优点:
1. 该方法不需要任何注入过程,这意味着攻击的特定行为不会被安全监测工具标记。
2. 不需要任何权限文件副本。大多数UAC绕过都需要权限文件副本以便在安全的位置获取恶意DLL来建立DLL劫持。因为任务调度程序复制了我们需要的东西到%TEMP%中,我们就不需要任何权限文件副本了。
3. 此方法在执行后会自动清理。在任务调度完成后(这时我们的恶意DLL已经加载完毕),任务会自动删除创建在%TEMP%的GUID文件夹(和其中的文件)。
4. 此方法在UAC级别设置为最高(“总是提醒”)的情况下适用,因为任务被设置成在“最高权限”下运行。大多数已有的UAC绕过方法依赖于IFileOperation COM对象来复制权限文件。IFileOperation使得UAC设置成“总是提醒”且即刻执行,这导致了提权文件副本失效:
该问题已经于2016年7月20日反映给微软安全响应中心(MSRC)。如我们所料,他们回应UAC不属于安全检测界限之一,如这里所述,这并不能被认定为安全漏洞。虽然这不算漏洞,但它确实能让攻击者使用各种不同于以前的绕过方式进行提权,并且指出了多个位置或者检查点需要被监控来观察攻击者的行为。
此问题可以通过使任务失效或者移除最高权限运行程序的请求来解决。另外,如果你想要检测这种攻击,你可以利用方法/签名来寻找新的WMI,这是用来监控攻击成功过程中新文件夹的建立这个步骤,因为肯定会有这一步。结合App/DLL白名单监控反常模块的加载(例如Sysmon event ID 7)也会限制这种攻击的成功。
文章原文链接:https://www.anquanke.com/post/id/84284