对比一下带病毒的与不带病毒的运行结果, 明显能发现前者运行时间非常长, 暗示病毒在后台收集敏感信息......

此外, 还多安装了一个 npm 包, 也就是病毒来源 plain-crypto-js
关于 step-security/harden-runner 的使用
这似乎是一个较为轻量化的包, 能快速设置网络规则, 尽管功能不是很完善, 有少量bug, 但可以让安全性上一个台阶
具体使用分为两个阶段, 审计阶段和规则模式
jobs:
job-name:
runs-on: ubuntu-latest
steps:
# Enable Network traffics rules
- name: Harden Runner
# 通过确保 name@hash 脚本本身稳定安全
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit # audit 为审计模式, block 为规则模式
首先, 什么也不用配置, 多跑几次工作流, 确保覆盖到全部情况. 此时, 脚本会监视每一个网络请求, 并自动创建报告.
你可以在 Summary 中看到信息, 并通过链接查看详情.

在对应的网站中, 会统计每一次运行访问到的域名, 并推荐一个规则列表:

理论上复制进去替换就行, 你也可以主动检查每一个域名和端口, 并进行调整, 可以使用类似的 *.domain.com 通配符匹配所有子域名, 但存在一些小问题(DNS解析不全, redirect 直接走 ip 可能会被拦截, 因此推荐完整域名).
除此之外, 还有一些小设置可以调整:
- name: Harden Runner
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: block # 规则模式
# 禁用遥测 (不会发送数据给网站, 因此最终看不到拦截结果)
disable-telemetry: true
# 不监视文件变化 (没啥用)
disable-file-monitoring: true
# 注意是管道符号 `>` , 每一行的字符串以空格隔开! 因此不允许注释和空格(源码中也是直接 `.split(" ")` 分割每条规则)
allowed-endpoints: >
api.github.com:443
cdn.jsdelivr.net:443
此次病毒分析
plain-crypto-js@4.2.1 是 crypto-js@4.2.0 的一个克隆版本,其 package.json 文件中新增了一个 scripts 块:
- "name": "crypto-js",
- "version": "4.2.0",
+ "name": "plain-crypto-js",
+ "version": "4.2.1",
"description": "JavaScript library of crypto standards.",
"main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "postinstall": "node setup.js"
+ },
"dependencies": {},
其中的 "postinstall" 钩子会在安装完成后自动被调用, 而恶意代码就藏在其中. 似乎虽然第三方安全审核没过, 但是你直接 npm install 时可不管这个. (应对方法就是 npm config set min-release-age=10 设置安全缓冲时间, 或禁用安装后的钩子 npm install --ignore-scripts axios )
这次攻击的脚本倒是没太多可圈可点的地方(常规操作), 但是时间线上有几个细节很有意思:
| 时间线(UTC) | 事件 | 亮点说明 |
| Mar 30, 23:59 | 包含恶意脚本的 plain-crypto-js@4.2.1 被发布 | 选择了一个很巧妙的时间, 发布完进入00:00, 这是定时任务的高发时间, 导致大量任务堆积而扫描不及时 |
| Mar 31, 00:05 | npm 安全扫描器自动将 plain-crypto-js 标记为恶意软件 |
| Mar 31, 00:21 | 引用了该库的恶意版本 axios@1.14.1 由被盗用的 jasonsaayman 账户发布 |
| Mar 31, 01:38 | Axios 维护者 DigitalBrainJS 提交了 PR #10591,为受损版本添加弃用警告。 | 维护者试图阻止用户安装最新新版本, 加入npm警告 |
| Mar 31, 01:42 | PR #10591 合并到主分支 | 还有人正好看到警告, 在PR中问怎么回事 |
| Mar 31, 02:19 | Ashish Kurmi(StepSecurity)在 issue #10597 报告了安全漏洞。该 issue 随后被jasonsaayman 账户删除 | 哈哈, 开始斗法了 |
| Mar 31, 02:19 | Ashish Kurmi 在 issue #10601 再次报告了安全漏洞。该 issue 随后被 jasonsaayman 账户删除 | issue 编号到了5位数, 是因为hacker一直用脚本创建 issue, 试图掩人耳目, 让维护者看不见真正的问题. |
| Mar 31, 03:00 | Ashish Kurmi 在 issue #10604 再次报告了安全漏洞。 | 应该是攻击结束, 骇客跑路了 |
| Mar 31, 03:25 | 姗姗来迟的 npm 收到问题报告, 删除了 plain-crypto-js 库 |
后续就是慢慢走流程了.
总体而言, 作为一个开源项目, 这次事件中 axios 维护者反应是相当及时的, 至少不是所有人都睡死过去了, 但恐怕当天晚上有不少人没机会睡觉了......