npm 包 Axios 供应链攻击事件分析
2026年3月31日,npm 生态系统中的一个关键组件——流行的 JavaScript HTTP 客户端 Axios 包遭遇了一次复杂的供应链攻击,导致其两个版本被植入恶意代码,从而部署了一个跨平台远程访问木马(RAT)。此次攻击并非传统的代码漏洞,而是通过窃取主维护者 npm 账户凭据,手动发布恶意版本,绕过了正常的 CI/CD 流程,展示了针对开源软件供应链的高度精密战术。
攻击概述
时间线与受影响版本
攻击者于2026年3月30日至31日期间,利用被盗的 npm 账户权限,发布了两个恶意版本的 Axios 包:[email protected] 和 [email protected]。 这些恶意版本在 npm 注册表上短暂存在了约3小时(UTC时间00:21至03:25)后被 npm 管理员移除,但在此期间仍可能被数百万用户下载。 攻击发生前,攻击者甚至提前18小时发布了一个“干净”版本的恶意依赖包 plain-crypto-js,以建立发布历史并规避新包扫描器的警报。
受影响的 Axios 版本及其特点如下表所示:
| 恶意版本 | 发布时间 (UTC) | 主要恶意载荷 | 主要攻击方式 |
|---|---|---|---|
[email protected] |
2026年3月31日 00:21 | [email protected] |
植入 Phantom Dependency |
[email protected] |
2026年3月31日 01:00 | [email protected] |
植入 Phantom Dependency |
攻击机制
此次攻击的核心在于劫持了 Axios 项目的主要维护者 jasonsaayman 的 npm 账户。 攻击者通过社会工程学手段诱骗维护者在其机器上安装了一个 RAT,从而窃取了用于发布 npm 包的凭据。 随后,攻击者将该账户的注册邮箱更改为 [email protected],一个受攻击者控制的 ProtonMail 地址。
值得注意的是,Axios 1.x 版本的合法发布通常通过 GitHub Actions 的 OIDC Trusted Publisher 机制进行,这是一种将发布过程加密绑定到经验证的 CI 工作流的方法。 然而,攻击者使用窃取的 npm 访问令牌手动发布了恶意版本 1.14.1 和 0.30.4,绕过了 OIDC 绑定,并且在 Axios 的 GitHub 仓库中没有对应的 commit、tag 或 release。
恶意版本本身并未直接修改 Axios 的核心源代码。 相反,攻击者在 package.json 文件中注入了一个名为 [email protected] 的“幻影依赖”(phantom dependency)。 这个依赖是一个伪装成合法加密库的恶意包,其唯一目的就是在安装过程中执行恶意代码。
技术细节分析
恶意依赖 plain-crypto-js
plain-crypto-js 包利用了“拼写混淆”(typosquatting)策略,其命名与著名的加密库 crypto-js 相似,旨在迷惑开发者和安全工具。 该包的核心恶意行为集中在其 package.json 文件中的 postinstall 钩子。
当用户通过 npm install axios 命令安装受感染的 Axios 版本时,npm 会自动解析依赖树并安装 plain-crypto-js。 此时,postinstall 脚本被触发,在后台静默执行一个高度混淆的 Node.js dropper 脚本 setup.js。
// package.json snippet from plain-crypto-js (simplified)
{
"name": "plain-crypto-js",
"version": "4.2.1",
"description": "A simple crypto library.",
"main": "index.js",
"scripts": {
"postinstall": "node setup.js"
},
"dependencies": {},
"repository": {
"type": "git",
"url": "https://github.com/some-repo/plain-crypto-js.git"
},
"keywords": [
"crypto",
"plain"
],
"author": "",
"license": "MIT"
}
setup.js 脚本采用了多种混淆技术来规避检测和逆向分析,包括字符串反转、Base64 解码和使用 XOR 密钥 OrDeR_7077 进行加密。 该脚本能够根据受害者的操作系统(Windows, macOS, Linux)下载并执行相应的第二阶段载荷。
载荷分析
最终部署的载荷是一个跨平台的远程访问木马(RAT)。 该 RAT 旨在执行侦察、建立持久性、窃取凭据等恶意活动。
- 功能:该 RAT 具备捕获 Web 浏览器和密码管理器中的凭据,以及与 GitHub、GitLab、Bitbucket、npm、Yarn、Python pip、RubyGems、Rust argo 和 .NET NuGet 相关的秘密信息的能力。 它还可以执行任意 DLL(Windows)、运行 PowerShell 命令、列出目录及文件元数据等。
- 跨平台实现:Windows 载荷可能是一个 Go 变体,而 macOS 载荷是一个 Nim-based 后门,名为 CosmicDoor,Linux 载荷也是定制化的。 三种平台特定的载荷都实现了相同的 RAT 功能,具有相同的 C2 协议、命令集、信标频率和伪造的用户代理字符串(如 IE8/Windows XP 用户代理),这成为了一个显著的检测指标。
- 反取证机制:为了逃避检测和阻碍取证分析,恶意包在执行后会删除其原始恶意文件,并通过替换受感染的
package.json文件来恢复其良性外观。 - C2 通信与归因:恶意载荷连接到已知的恶意命令与控制(C2)服务器以下载第二阶段载荷。 Microsoft 威胁情报团队已将此攻击基础设施和 Axios npm 攻击归因于名为 Sapphire Sleet 的朝鲜国家行为者(亦称 UNC1069)。
CVE 编号
值得注意的是,此次事件并非传统的 CVE(Common Vulnerabilities and Exposures)漏洞,而是典型的软件供应链攻击。 CVE 主要用于标识和追踪软件代码中的已知漏洞,而供应链攻击则利用信任关系和分发机制。因此,依赖于 CVE 的传统漏洞管理流程可能无法有效识别和响应此类事件。
影响范围与检测
广泛的影响
Axios 是 JavaScript 生态系统中最受欢迎的 HTTP 客户端之一,每周 npm 下载量超过1亿次,拥有174,000个依赖包。 这意味着受影响范围极其广泛,包括使用 Axios 的 Web 应用程序、服务和 CI/CD 流水线。
此次攻击主要发生在安装/构建阶段,而非应用程序运行时。 因此,即使最终用户使用的应用程序依赖于受感染的 Axios 版本,通常也不会直接执行 RAT。但任何在受影响窗口内运行 npm install 的开发或构建机器都应被视为已受感染。
受感染系统的指标 (IOCs)
如果您的系统安装了 [email protected] 或 [email protected],应检查以下 IOCs:
- 依赖树中存在
plain-crypto-js:这是最直接的指标。 - npm 账户邮箱更改:Axios 维护者的 npm 账户邮箱被更改为
[email protected]。 - 平台特定载荷文件:
- Windows:
%PROGRAMDATA%\system.exe(或类似路径) - macOS/Linux: 侦察和持久化机制,可能涉及隐藏文件或服务。
- Windows:
- 网络流量到 C2 服务器:与已知的恶意 C2 域进行通信。
- 日志中的
postinstall脚本执行。
检测方法
组织应立即采取以下步骤来确定是否受到影响:
- 检查 lockfile:在
package-lock.json或yarn.lock中查找是否包含[email protected]或[email protected]。# 检查 package-lock.json grep -E '"axios"' package-lock.json | grep -E '1\.14\.1|0\.30\.4' # 检查 yarn.lock grep -E 'axios@' yarn.lock | grep -E '1\.14\.1|0\.30\.4' - 检查恶意依赖:在依赖树或
node_modules目录中查找plain-crypto-js包。# 检查依赖树 npm ls plain-crypto-js # 直接搜索 node_modules find node_modules -name "plain-crypto-js" -type d - 审查 CI/CD 日志:检查在攻击窗口内运行的 CI/CD 作业,特别是
npm install或npm ci的输出,看是否包含受影响的 Axios 版本或plain-crypto-js。 - 审查遥测数据:识别潜在的 IOCs,例如异常的网络连接或进程行为。
缓解措施
对于已安装 [email protected] 或 [email protected] 的系统,应立即采取以下缓解措施:
- 回滚到安全版本:将 Axios 降级到已知安全版本,例如
[email protected]或[email protected]。 - 强制锁定依赖版本:在
package.json中明确指定并锁定 Axios 及其所有传递依赖的版本,避免使用“^”或“~”等模糊的版本范围。 - 清理 npm 缓存:执行
npm cache clean --force以确保所有本地缓存的恶意包都被清除。 - 禁用或限制自动化依赖更新:对于关键包,暂时禁用或严格限制自动化依赖更新工具或机器人。
- 采用 OIDC Trusted Publishing:利用 OpenID Connect (OIDC) Trusted Publishing 机制来消除存储的凭据,提高发布安全性。
- 轮换所有凭据和令牌:在所有受影响的机器上,以及可能通过这些机器访问的任何服务(如 npm、GitHub、云平台)上,立即轮换所有凭据和 API 令牌。
- 重新格式化受损系统:最安全的做法是对任何运行过恶意安装的系统进行重新格式化和重新部署。
- 审查和加固 CI/CD 流水线:实施更严格的审查机制,例如对所有新发布或更新的依赖进行运行时行为分析,并确保构建环境的隔离。