找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4911

积分

0

好友

679

主题
发表于 4 天前 | 查看: 34| 回复: 0

上亿台电脑可能因一次 npm install 而沦陷,这个始于一次看似平常的版本更新的故事,细思极恐。

2026年3月30日,全球最流行的 JavaScript HTTP 库 axios 被黑客成功劫持。攻击者仅通过发布两个版本——1.14.1 和 0.30.4——就在短短 2 小时内,将恶意代码植入了至少数百万开发者的电脑。

axios 每周下载量超过 1 亿次,几乎是所有前端和后端 Node.js 项目的标配。如果你使用过 Vue、React 或任何 Node.js 后端服务,大概率都依赖它。而这一次,攻击者用一种极其隐蔽的方式,在你毫无察觉的情况下,在你的系统中埋下了一个远程访问木马。

一次看似正常的“版本更新”

一切始于一个普通的版本号。

3月30日深夜,一个名为 jasonsaayman 的账号在 npm 上发布了 axios@1.14.1。39分钟后,同一个账号又发布了 axios@0.30.4

从表面看,一切如常。版本号符合预期,发布者也是 axios 的官方维护者。没有任何人意识到:

这两个版本里,藏着致命的恶意代码。

攻击者在这两个版本的 package.json 中偷偷加入了一个从未有过的依赖项:

"plain-crypto-js": "^4.2.1"

这是一个从未在 axios 源代码中被 importrequire 的包。它存在的唯一目的,就是为了触发一个恶意的 postinstall 脚本。一旦脚本运行,木马便随之而来。

攻击全流程复盘:精密如外科手术

回顾这次攻击,其精密程度令人脊背发凉。

第一步:提前布局,建立信任

攻击提前18小时开始布局。攻击者先在 npm 上发布了一个“干净”的包——plain-crypto-js@4.2.0。这个包看起来完全正常,只是一个加密库的副本,没有任何恶意代码。其作用是建立发布历史,让这个账号看起来像一位合法的维护者,为后续攻击铺平道路。

18小时后,攻击者发布了关键的 4.2.1 版本——这次,恶意代码被藏了进去。

第二步:劫持维护者账号

jasonsaayman 是 axios 的核心维护者之一。攻击者成功入侵该账户,将其邮箱更改为攻击者控制的 ifstap@proton.me,并利用这个被盗的账户发布了那两个恶意版本。

这里有一个关键细节:正常情况下,axios 的所有发布都应通过 GitHub Actions 的 OIDC 可信发布机制进行,发布记录会绑定加密签名。但 1.14.10.30.4 这两个版本没有。这表明它们是通过被盗的 npm token 手动发布的,巧妙地绕过了正常的 CI/CD 安全检查流程。

第三步:注入恶意依赖

如前所述,恶意依赖被悄悄注入 package.json。值得注意的是,在整个 axios 源码库中搜索 plain-crypto-js 都不会有任何结果。它纯粹是为了触发 postinstall 钩子而存在。

第四步:木马启动与自我销毁

当开发者运行 npm install axios@1.14.1 时,npm 会自动安装 plain-crypto-js,并执行其 postinstall 脚本。

这个脚本会执行一系列操作:

  1. 检测目标操作系统(Windows、macOS 或 Linux)。
  2. 向攻击者的命令与控制服务器 sfrclak.com:8000 发送请求。
  3. 下载针对该操作系统的第二阶段恶意负载。
  4. 立即删除自身,并替换 package.json 为一个“干净”版本。

整个过程可能不到2秒。在 npm 还在解析依赖树时,木马已完成攻击并清除了现场证据。

事后检查 node_modules,你什么都看不出来。包目录依然存在,版本号可能显示为 4.2.0——因为攻击者早已完成了偷梁换柱。

三平台无差别攻击:Windows、macOS、Linux无一幸免

这或许是迄今为止最“全面”的软件供应链攻击之一,覆盖了所有主流开发者平台。

  • macOS 版本:木马伪装成 AppleScript,写入 /tmp/6202033,然后下载一个名为 com.apple.act.mond 的二进制文件到 /Library/Caches/ 目录下,使其看起来像是苹果官方的缓存进程。
  • Windows 版本:更为隐蔽。它会定位系统的 PowerShell,将其复制一份到 %PROGRAMDATA%\wt.exe(伪装成 Windows Terminal),然后通过 VBScript 静默执行恶意的 PowerShell 脚本。
  • Linux 版本:直接使用 curl 下载一个 Python 脚本到 /tmp/ld.py,并通过 nohup 命令在后台运行。

攻击者为每个平台分配了不同的标识符:macOS 对应 product0,Windows 对应 product1,Linux 对应 product2。这种精细化程度,已远超普通黑客攻击,展现出职业级 APT 攻击的水准。

2小时53分钟的紧急响应与下架

值得庆幸的是,这次攻击被相对迅速地发现了。

网络安全公司 StepSecurity 的 AI Package Analyst 在第一时间捕获了异常。他们的 Harden-Runner 工具在多个项目的 CI/CD 流程中检测到了对可疑地址 sfrclak.com:8000 的外向连接。

3月31日凌晨3点15分,npm 官方紧急下架了这两个恶意版本。从发布到删除,总共经历了不到3小时。

然而,对于供应链攻击而言,3小时已经足够漫长。

如果你在这期间恰好执行了 npm install 或相关构建命令,你的电脑可能已经处于风险之中。

真正令人后怕之处

现在,让我们思考一个关键问题:

你如何确定自己的电脑此刻是安全的?

axios 官方已经删除了恶意版本,但你 macOS 上的 /Library/Caches/com.apple.act.mond 是否已被清除?你 Windows 上的 %PROGRAMDATA%\wt.exe 是否还在运行?你 Linux 系统上的 /tmp/ld.py 进程是否已被终止?

攻击者部署的是一个持久化后门。即使你之后将 axios 升级到了安全版本,那个隐藏的恶意负载可能仍在后台静默运行,持续接收攻击者的指令。

这正是供应链攻击最可怕的地方——它利用的不是软件漏洞,而是生态系统中的信任。你信任 axios,信任 npm,信任那个维护者账号。而攻击者只需攻破其中一环,就能让全球开发者为其“传播”恶意代码。

行业需要彻底反思

事件发生后,社区评论中有一句话直指核心:

“Batteries included” ecosystems are the only persistent solution.

翻译过来就是:减少对第三方依赖的滥用,才是根本的解决之道。

axios 的核心功能——发送 HTTP 请求——现代浏览器的原生 fetch API 或 Node.js 的内置模块也能实现。我们之所以选择 axios,往往是出于“生态习惯”。而这份习惯,如今成了攻击者最锋利的突破口。

社区和安全专家给出了几条具体的防御建议:

  • 设置 min-release-age:在包管理器中配置规则,禁止安装发布不足7天的新包,为安全团队留出分析和响应时间。
  • 使用 ignore-scripts:全局禁用 npmpostinstall 等脚本执行功能,至少在 CI/CD 环境中强制禁用。
  • 强制可信发布:npm 等平台应要求高下载量的核心包必须使用 OIDC 等可信发布机制,彻底禁止使用长期有效的手动 token 进行发布。

最后一点尤为关键。如果 axios 的发布流程被强制绑定在 GitHub Actions 上,即使攻击者窃取了密码,也无法发布恶意包——OIDC token 是临时的、情境绑定的,难以被窃取重用。

遗憾的是,这些防御措施目前尚未成为行业的普遍标准。


你最近一次运行 npm install 是什么时候?

是时候检查一下了。打开终端,执行以下命令:

npm list axios | grep -E “1\.14\.1|0\.30\.4”
ls node_modules/plain-crypto-js

如果命令没有任何输出,那么恭喜你,大概率是安全的。

如果发现了相关版本,请不要犹豫,立即按照系统已被入侵的流程进行排查和处理。

这次攻击堪称对开源软件供应链信任体系的一次精准打击。整个行业或许真的需要从“依赖狂欢”中冷静下来,重新审视“少即是多”的原则。如果你想了解更多此类深度技术安全分析,可以到 云栈社区 的开发者广场板块,与其他同行交流探讨。




上一篇:Jürgen Schmidhuber指控Yann LeCun学术抄袭:JEPA架构与30年前PMAX论文高度相似
下一篇:区块链架构六层模型与共识算法精讲:智能合约实战与应用场景解析
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-4-7 21:15 , Processed in 0.608620 second(s), 43 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表