Millions of JS devs just got penetrated by a RAT…

Fireship Youtube

上周Axios被投毒这事,我觉得比事件本身更值得聊的是攻击者的耐心。

你可能已经在各种群里看到预警了:Axios 1.8.0到1.8.6这几个版本被植入了RAT(远程访问木马)。作为一个周下载量4000万的HTTP库,这次中招影响面确实够大。但如果你只是想知道"我该怎么办",答案很简单:检查package.json,如果用了这几个版本就降回1.7.9或者升到官方已经清理过的版本,然后该rotate密钥rotate密钥。

我更想说的是这次攻击的手法。攻击者没有选择那种"广撒网"的supply chain攻击——比如往一堆小库里塞挖矿脚本。他们盯上的是Axios这种"基础设施级"的依赖,然后等。等maintainer的某个账号权限泄露,或者某个CI/CD环节出现漏洞。一旦拿到发布权限,立刻推送看起来正常的版本更新,木马代码藏在混淆后的构建产物里。这种攻击的ROI高得吓人:一次成功的渗透,换来的是数百万开发环境和生产服务器的潜在后门。

这让我想起去年event-stream事件的翻版,但这次更精准。攻击者显然做过功课,知道JavaScript生态里大家对依赖更新的态度——"能用就不升级"和"自动化依赖更新"这两派人正好都中招:前者可能早就锁在了有问题的版本上,后者的CI可能自动拉取了恶意版本并部署到生产。

说实话,这种攻击防不胜防。你可以用Dependabot扫漏洞,可以开启npm的2FA,可以锁package-lock.json,但这些都只能降低风险。真正的问题在于我们的依赖链太长了——一个普通的React项目,node_modules里躺着上千个包,你真的知道它们都在干什么吗?每次npm install的时候,你实际上是在对几百个陌生人说"我信你"。

有人会说这是开源的原罪,我不这么看。开源的问题不是信任模型,而是我们把"方便"看得太重了。为了少写几行HTTP请求代码,我们引入一个40KB的库;为了处理日期,我们拉进来moment.js;为了deep clone一个对象,我们装lodash。每一次npm install,都是在扩大攻击面。

如果你的项目里用了Axios的受影响版本,现在要做的不只是升级版本。你得假设攻击者已经拿到了你的环境变量、API keys、甚至代码仓库的访问权限。这不是危言耸听——这个RAT的设计目标就是远程控制,不是简单的数据窃取。

最后问一句:你上次audit自己项目的依赖树是什么时候?