Axios npm 恶意包供应链攻击分析
2026年3月31日,JavaScript生态系统中最受欢迎的HTTP客户端库Axios遭遇了一起严重的供应链攻击。攻击者劫持了Axios主要维护者的npm账户,并在npm官方仓库发布了两个被污染的恶意版本:[email protected]和[email protected]。这些恶意版本在安装时会引入一个名为plain-crypto-js的隐藏恶意依赖,其唯一目的是在开发者执行npm install期间自动触发,静默释放针对Windows、macOS和Linux系统的远程访问木马 (RAT),窃取环境凭据并控制机器。
攻击概述与影响范围
此次攻击利用了npm包管理机制中的postinstall钩子来触发恶意行为。当开发者或自动化系统安装受污染的Axios版本时,npm会自动下载嵌套依赖plain-crypto-js。该恶意依赖随后根据操作系统下载并执行对应的远程控制载荷(C2 payload)。恶意脚本执行后会尝试销毁痕迹,并覆盖原始配置文件以抹除审计线索,使得企业难以察觉入侵痕迹。
此次攻击的目标是同时针对Axios的当前和旧版分支,以最大化在生态系统中的影响范围。任何在攻击暴露窗口期(2026年3月31日 UTC 00:21至03:15)安装了[email protected]或[email protected]的开发环境、CI/CD流水线或生产环境都可能受到影响。
受影响的Axios版本:
| 包名 | 受影响版本 | 恶意依赖 | 攻击时间 (UTC) |
|---|---|---|---|
axios |
1.14.1 (最新版本) |
[email protected] |
2026年3月31日 00:21 - 03:15 |
axios |
0.30.4 (旧版本) |
[email protected] |
2026年3月31日 00:21 - 03:15 |
攻击技术分析
维护者账户劫持与恶意更新
此次攻击的核心是攻击者劫持了Axios主要维护者(jasonsaayman)的npm账户。攻击者将该账户的注册邮箱更改为攻击者控制的ProtonMail地址。
值得注意的是,合法的Axios 1.x版本发布通常通过GitHub Actions与npm的OIDC Trusted Publisher机制进行,这在加密上将发布与经过验证的CI/CD工作流绑定。然而,恶意版本[email protected]是通过窃取的npm访问令牌手动发布的,没有OIDC绑定,也没有相应的commit或tag在Axios的GitHub仓库中。这意味着该恶意发布仅存在于npm注册表中。
攻击者提前18小时部署了恶意依赖[email protected],伪装成合法的crypto-js库,以此绕过针对“最新发布包”的安全扫描告警。
恶意载荷通过plain-crypto-js包的package.json文件中配置的postinstall生命周期钩子触发。
{
"name": "plain-crypto-js",
"version": "4.2.1",
"description": "A lightweight JavaScript library for cryptographic functions.",
"main": "index.js",
"scripts": {
"postinstall": "node setup.js"
},
"keywords": [
"crypto",
"javascript",
"security"
],
"author": "anonymous",
"license": "MIT"
}
当npm install执行时,setup.js脚本会立即运行,连接命令与控制(C2)服务器,并下载针对不同操作系统的远程访问木马 (RAT)。
恶意载荷行为
- 凭据窃取: 恶意代码立即执行,窃取系统中的敏感凭据,包括云访问密钥、数据库密码、API令牌等。
- RAT安装: 在受感染的机器上安装远程访问木马,使攻击者能够持久访问。
- 跨平台: 恶意载荷能针对macOS、Windows和Linux系统进行攻击。
- 自毁机制: 恶意软件执行后会尝试移除安装痕迹,并用干净的版本替换其自身的包元数据,以逃避取证检测。
在Windows系统上,恶意软件甚至在重启后仍能保持持久性。这意味着攻击者可以利用受感染的开发者机器作为立足点,访问源代码仓库、云凭据、CI/CD流水线和生产基础设施,从而将单个受感染的笔记本电脑变为更广泛攻击的通道。
典型npm供应链攻击向量
除了此次Axios事件中观察到的维护者账户劫持和恶意更新,npm生态系统中还存在其他常见的供应链攻击向量:
Typo-squatting (拼写劫持/错拼包攻击)
攻击者发布名称与流行合法包相似的恶意包,利用开发人员的拼写错误或自动化系统解析错误来诱骗其下载。
- 机制: 攻击者注册与流行包(例如
axios)名称非常相似的恶意包,可能只修改一两个字母,或改变大小写,例如axois或Axios(如果原包是小写)。 - 示例: 历史上有
eslint-scope与eslnt-scope的案例。 即使是微妙的大小写差异也可能被利用。 - 载荷: 这些恶意包可能包含窃取凭据、安装后门或运行加密矿工的代码。
Dependency Confusion (依赖混淆攻击)
这种攻击利用了包管理器在私有和公共注册表之间解析依赖项时的缺陷。
- 机制: 当组织同时使用私有(内部)注册表和公共注册表(如npmjs.com)时,攻击者识别出私有包的名称,并在公共注册表上发布同名但版本号更高的恶意包。包管理器通常会优先选择版本号最高的包,从而错误地拉取并安装恶意公共包,而非预期的私有包。
- 示例: Alex Birsan在2021年披露了这种攻击,并成功在微软、苹果等公司进行了概念验证。
- 防御: 使用带有作用域的包(scoped packages),例如
@myorg/mypackage,或在.npmrc文件中明确指定注册表优先级。
恶意维护者行为/蓄意破坏
与账户劫持不同,这种攻击是包的合法维护者故意在自己的包中引入恶意代码。
- 机制: 维护者因各种原因(例如抗议开源软件的商业利用)决定破坏其维护的包。
- 示例: 2022年1月,
colors.js和faker.js库的维护者Marak Squires故意引入了恶意更新,导致这些包进入无限循环,从而使数千个依赖它们的应用崩溃,造成了拒绝服务 (DoS) 攻击。colors.js每周下载量超过2000万次,faker.js每周下载量超过250万次,影响范围巨大。
缓解与检测策略
针对npm供应链攻击,组织和开发者应采取多层防御策略:
立即排查与补救
针对Axios事件,需要立即排查开发环境、CI/CD流水线及生产服务器。
- 核查高危版本: 重点检索项目依赖树中是否存在
[email protected]或0.30.4版本,并检查node_modules目录下是否包含plain-crypto-js文件夹。若发现,则环境已感染。 - 清理npx缓存: 使用AI CLI工具的企业需立即清理npx缓存。Windows系统删除
%LOCALAPPDATA%\npm-cache\_npx目录;macOS及Linux系统删除~/.npm/_npx目录。 - 隔离与重建: 受感染机器应立即从网络隔离,不应尝试原地清理,而应从已知良好镜像重建。
- 凭据轮换: 轮换所有受影响系统上的凭据,包括npm令牌、SSH密钥、云服务凭据、CI/CD秘密等。
- 阻断C2通信: 在网络/DNS层面阻断攻击者的命令与控制服务器地址。
防御性措施
- 严格依赖版本锁定: 在
package.json文件中严格指定组件的安全版本(例如明确锁定[email protected]),禁止使用latest等模糊版本号,以防止自动拉取未经验证的版本。 使用package-lock.json或yarn.lock文件来锁定依赖版本及其哈希值,并通过npm ci命令强制使用lockfile,可以有效防止依赖被篡改。 - 禁用自动脚本: 在全局环境执行
npm config set ignore-scripts true,禁止preinstall,install,postinstall等生命周期脚本自动运行。 - 启用多因素认证 (2FA) 及Trusted Publishing: 强制npm账户启用2FA,尤其对发布操作。 npm已集成Sigstore的Trusted Publishing功能,通过OIDC(OpenID Connect)将包发布与可验证的CI/CD工作流绑定,无需在构建系统中管理API令牌。 开发者应优先使用此机制而非传统的npm令牌。
- 持续安全审计与扫描: 定期对项目依赖进行安全审计。使用
npm audit来识别已知漏洞。集成Snyk, Dependabot, Black Duck SCA等自动化工具,在开发生命周期的早期检测恶意或易受攻击的依赖。 - 行为监控与异常检测: 部署能够监控异常包行为的工具,例如下载远程脚本、窃取环境变量或在安装时启动shell等。 Splunk的Package-Inferno等工具可以检测行为威胁。
- 软件物料清单 (SBOM): 生成并分享SBOM,提供依赖关系的透明度,有助于快速评估漏洞。
- OpenSSF Scorecards: 使用OpenSSF Scorecard项目评估开源项目的安全状况,该工具通过一系列自动化检查来监测开源软件的健康状况,并提供安全评分。