利用Winrm.vbs绕过白名单限制执行任意代码

winrm.vbs内部的逻辑验证了这一点

绕过措施描述

winrm.vbs(一个位于system32目录下的具有Windows署名的脚本文件)可以被用来调用用户定义的XSL文件,从而导致随意率性的、没有署名的代码履行当用户向winrm.vbs供给’-format:pretty’或者’-format:text’参数时,winrm.vbs将从cscript.exe所在目录读取WsmPty.xsl或Wsmtxt.xsl文件这意味着若将cscript.exe拷贝到进击者可以节制的目录下,并将恶意的XSL文件也置于相同路径中,进击者将可以绕过署名保护而履行随意率性代码这个进击手段和Casey Smith的wmic.exe技巧很相像

绕过措施的POC

全部事情流程如下所示:

1.在进击者可以节制的目录中放置恶意的WsmPty.xsl或者WsmTxt.xsl文件

2.拷贝cscript.exe或者wscript.exe到相同的目录中

3.根据第一步中的恶意XSL文件(WsmPty.xsl或者WsmTxt.xsl),履行winrm.vbs并供给不合的参数(‘-format:pretty’或者’-format:text’)下面是一个恶意XSL文件的例子该文件可以被放置到上述第一步中的路径中(对付这个例子来说,是C:BypassDirWsmPty.xsl):

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”>

ms:script>

stylesheet>

一个加倍有进击意义的XSL文件可以履行经由过程DotNetToJScript天生的Payload,导致进击者可以使用该伎俩履行随意率性不具有署名的代码在放置了恶意XSL文件后,以下的批处置惩罚文件可以被用来启动paylaod:

mkdir %SystemDrive%BypassDir

copy %windir%System32cscript.exe %SystemDrive%BypassDir

%SystemDrive%BypassDircscript //nologo %windir%System32winrm.vbs get wmicimv2/Win32_Process?Handle=4 -format:pretty

我是若何发明该问题的

我发明这个问题完全是出于偶尔我曾和Casey一路钻研使用wmic.exe的XSL绕过措施,不久之后,我又开始反省系统自带的各类VBS和JScript文件,探求更多的绕过措施我之以是开始反省这些自带的脚本是由于Matt Nelson的.vbs注入技巧给了我启迪当我在查阅winrm.vbs源码的时刻,文件中的’WsmPty’以及’WsmTxt’顿时引起了我的留意,由于Casey曾经在他的博客中说过,对付应用了XSL的文件,它们可以经由过程在XSL文件中嵌入WSH脚本内容而拥有履行随意率性代码的潜力毫无疑问,winrm.vbs也不例外我异常重视于探求这些具备Windows署名的,并可以导致随意率性代码履行的脚本或者二进制文件这是由于它们不仅可以绕过利用白名单的防御,同时它们也不轻易被安然软件反省出来(至少当它们还没有被公布的时刻)我会不停都在探求它们的路上!

检测策略

若要对上述的措施做出有效的检测和防护,探求这类进击手段所必要的最小组件聚拢是很紧张的

进击者节制的WsmPty.xsl或者WsmTxt.xsl文件必然会被创建

winrm.vbs硬编码了这两个文件的名字,并明确将这两个文件同’pretty’或者’text’参数绑定到了一路今朝来看,这两个文件只可能当前事情目录中被获取(多半环境下便是cscript.exe所在的目录),而不太可能被重定向到其他位置从戍守的角度上来说,若一个WsmPty.xsl或WsmTxt.xsl文件与它们在System32目录下的版本具有不合哈希值,则我们可以觉得这个XSL文件是可疑的幸运的是,合法的XSL文件很少会有变更

一个具有有效署名的winrm.vbs会被履行若要使用本文的绕过措施,进击者不能改动winrm.vbs的内容

经由过程在敕令行中探求’winrm.vbs’字符串这种防御手段是不够的,由于进击者可以随意率性改动winrm.vbs的文件名

调用winrm.vbs时的’format’参数必须指定为’pretty’或’text’,这样winrm.vbs才会调用对应xsl文件

进击者不仅仅可以采纳’format’参数,下面的变种形式也是可以的(大年夜小写敏感):

-format:pretty

-format:”pretty”

/format:pretty

/format:”pretty”

-format:text

-format:”text”

/format:text

/format:”text”

若仅仅查找’format’字符串可以检测到上述的所有变体,这种措施带来的误报会很多’format:’后面所接内容的合法与否将取决于详细的公司情况不过,对xsl文件的合法引用更多的滥觞于system32目录下的csript.exe和winrm.vbs文件,而不会滥觞于其他位置

winrm.vbs应该是被cscript.exe履行的

winrm.vbs经由过程验证WScript.FullName是否包孕了字符串’cscript.exe’这一点来验证其自身是被cscript.exe履行的这个验证本身是不敷完善的,由于它仅仅反省可履行文件的路径中是否包孕’cscript.exe’字符串这将导致进击者可以从一个被重命名过的cscript.exe启动winrm.vbs,以致可以用其他的脚本说冥器(例如wscript.exe)来启动winrm.vbs下面的批处置惩罚法度榜样的例子说清楚明了若何绕过winrm.vbs脚本中对’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办事被启用有很多的选项都可以支持’format’参数

足够壮实的检测手段不应该从敕令行中检测’cscript.exe’或者’wscript.exe’作为判断依据只管假如进击者没有克意规避检测,这种检测措施可以检测到上文所述的进击手段,然则进击者若是将script.exe拷贝并重命名,检测手段就对此力所不及了一个加倍壮实的检测措施应该斟酌检测二进制文件的署名以及它的’原始文件名’’原始文件名’这一属性被嵌入到了二进制文件之中,并被署名所保护,而假如进击者想要改动这一属性,二进制文件的署名将会掉效

[1] [2] [3] [4]下一页

缓解和阻拦步伐

本文提到的绕过措施可以经由过程启用Windows Defender Application Control(WDAC)的User Mode Code Integrity(UMCI)选项来阻拦因为今朝并没有其他有效的措施阻拦这些具有Windows署名的脚本文件运行,具有要挟的脚本文件将经由过程其哈希值被禁用不过获取各个版本的脚本文件的哈希值会是很艰苦的,斟酌到Windows如斯宏大年夜的版本数量这篇博客具体阐清楚明了为什么经由过程哈希值禁用文件是不高效的至于缓解步伐,微软可以改动这个脚本文件的内容并从新进行署名假如这样做的话,这将导致之前版本的脚本文件的署名掉效以是假如我们经由过程WDAC启用了脚本履行的署名保护,这些脚本的履行将掉败然而,这样的场景只能阻拦一个非治理员账户进行进击,由于进击者可以经由过程治理员权限安装微软之前版本的catalog署名,从而规复脚本文件的署名信息上述的阻拦懈弛解步伐都依附于WDAC的开启斟酌到今朝有大年夜量企业并没有开启WDAC,就算winrm.vbs被微软修复,也没有什么步伐可以阻拦进击将旧版本的winrm.vbs文件放在系统中并加以使用是以,就算微软修复了winrm.vbs的问题,今朝也没有真正足够壮实的措施可以防护此问题

WSH/XSL脚本检测

这不是第一次WSH/XSL被进击者滥用,也不会是着末一次进击者应该必要懂得它们的payload到底是从磁盘中的文件被履行或者是完全在内存中被履行经由过程ScriptLogging技巧,Powershell完全具有这种能力然而对付WSH来说,它们却不具备类似的能力然而,只要你对付ETW认识,使用Antimalware Scan Interface(AMSI)捕获WSH的内容是完全可能的AMSI经由过程Microsoft-Antimalware-Scan-Interface ETW Provider被裸露出来假如你想考试测验获取ASMI事故,KrabsETW是你可以采纳的最好的库之一不过,若仅仅出于实验目的,你可以经由过程logman.exe获取ETL记录下面的例子可以开始和停息ETL的记录,并将ASMI相关的事故记录到ASMITrace.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’这一EWT Provider,并且上文中的’Event1′又是从何而来我是经由过程logman query providers这一敕令查找已注册providers的名称的’Event1′这一关键字对应着捕获ASMI信息为了找到这个关键字,我经由过程perfview.exe将ETW清单文件导出到XML这个清单文件可以让你很清楚地懂得到经由过程这一provider到底可以查询到哪些事故

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”>

上一页[1] [2] [3] [4]下一页

stringTable>

string id=”keyword_Event1″ value=”Event1″/>

string id=”task_task_0″ value=”task_0″/>

stringTable>

resources>

localization>

instrumentationManifest>

在捕获到ETL记录后,你就可以自己随意率性选择对象来进行阐发Get-WinEvent这一powershell敕令就可以很好的解析ETL记录我写了一个简单的脚原先解析ASMI事故必要留意的是,WSH无法供给’contentname’这一属性,导致我们不得不手动解析这一事故信息这个脚本也会捕获到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)).WordStr(‘-‘, ”)

[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

上一页[1] [2] [3] [4]下一页

$AppName = $_.Properties[3].Value

$ContentName = $_.Properties[4].Value

$Content = [Text.Encoding]::Unicode.GetString($_.Properties[7].Value)

$Hash = [BitConverter]::ToString($_.Properties[8].Value).WordStr(‘-‘, ”)

$ContentFiltered = $_.Properties[9].Value

[PSCustomObject] @{

Session = $Session

ScanStatus = $ScanStatus

ScanResult = $ScanResult

AppName = $AppName

ContentName = $ContentName

Content = $Content

Hash = $Hash

ContentFiltered = $ContentFiltered

}

}

}

$AMSIScanEvents

在成功捕获之后,你就可以看到此次履行payload的内容了pic here使用ETW进行相关检测并不是这篇文章的主题,不过盼望这篇文章能够让你孕育发生足够的兴趣,让你之落后行深入钻研

表露光阴线

为了避免我们表露此问题后,进击者使用该破绽造成不良影响,我们一样平常会先向厂商申报破绽并供给足够多的光阴让它们修复问题因为本文的破绽涉及到Windows Defender Application Control,我们将这个问题供给给了Windows全部光阴线如下所示

April 24, 2018 — 向MSRC申报此问题

April 24, 2018 — MSRC知晓了问题并供给了一个事故编号

April 30, 2018 — 收到邮件,奉告我们该问题已被复现

May 24, 2018 — 向MSRC发送邮件,要求更新

May 28, 2018 — 回覆称评估历程仍在继承

June 10, 2018 — 向MSRC发送邮件,要求更新

June 11, 2018 — MSRC回覆称计划在8月更新中修复问题

July 12, 2018 — MSRC回覆称该问题不能经由过程安然更新要领办理,可能会鄙人一个版本更新中修复此问题

上一页[1] [2] [3] [4]

赞(0) 打赏
分享到: 更多 (0)
免责申明:本站所有资料均来自于网络,版权归原创者所有!本站不提供任何保证,不保证真实性,并不承担任何法律责任

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

阿里云优惠网 更专业 更优惠

阿里云优惠券阿里云大礼包