如何利用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)

相关推荐

  • 如何理解Java快速开发平台J-Hi

    技术如何理解Java快速开发平台J-Hi如何理解Java快速开发平台J-Hi,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。J-HI是什么J-HI是一款J

    攻略 2021年11月21日
  • 数据库迁移如此复杂的原因是什么

    技术数据库迁移如此复杂的原因是什么这篇文章主要介绍“数据库迁移如此复杂的原因是什么”,在日常操作中,相信很多人在数据库迁移如此复杂的原因是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”

    攻略 2021年10月23日
  • 怎么部署skywalking容器

    技术怎么部署skywalking容器本篇内容主要讲解“怎么部署skywalking容器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么部署skywalking容器”吧!1.

    攻略 2021年11月16日
  • Form表单使用、ajax解决表单提交后页面跳转数据丢失的问题缺点

    技术Form表单使用、ajax解决表单提交后页面跳转数据丢失的问题缺点 Form表单使用、ajax解决表单提交后页面跳转数据丢失的问题缺点一、Form表单基本使用
    表单概念:在网页中主要负责 数据采集功

    礼包 2021年10月19日
  • windows API怎么使用入门sleep

    技术windows API怎么使用入门sleepwindows API怎么使用入门sleep,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。windows

    攻略 2021年10月23日
  • javascript如何删除非数字的字符

    技术javascript如何删除非数字的字符本篇内容介绍了“javascript如何删除非数字的字符”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大

    攻略 2021年12月8日