node-ipc供应链投毒事件深度解析

node-ipc 供应链投毒事件深度解析:一个过期域名如何劫持千万级 npm 包

2026年5月14日,npm 生态遭遇年度最严重供应链攻击。攻击者仅凭一个过期邮箱域名,就将拥有千万级下载量的 node-ipc 库变成了窃取全球开发者凭证的武器。69 万次下载、90+ 类凭证目标、DNS 隧道外传——这起事件重新定义了供应链安全的底线。这次事件让我们不得不思考:一个看似微不足道的域名过期,竟能引发如此巨大的安全灾难,我们的开源生态到底还有多少这样的"定时炸弹"?

攻击全链路拆解

准备阶段:一个被遗忘的域名

攻击者没有使用 0day、没有社工、没有入侵 CI/CD。他们做了一件更简单的事:

1
2
2025-01-10  维护者 atiertant 的邮箱域名 atlantis-software.net 过期
2026-05-07  攻击者通过 Namecheap 重新注册该域名

这就是整个攻击链的起点。在 npm 生态中,维护者的邮箱就是账号恢复的唯一凭证。域名过期等于邮箱可控,等于账号可控。

劫持阶段:密码重置一击即中

1
2
3
4
5
6
7
8
9
攻击者配置 atlantis-software.net 的 MX 记录
访问 npmjs.com → "忘记密码" → 输入 [email protected]
npm 发送密码重置链接到攻击者控制的邮箱
重置密码 → 获得 atiertant 账号完全控制权
该账号拥有 node‑ipc 包的发布权限

关键问题:atiertant 是 2022 年 “peacenotwar” 事件后被添加为维护者的,但此后从未发布过任何版本。这是一个典型的休眠账号——拥有高权限,却几乎没有安全防护。

投毒阶段:多版本覆盖策略

攻击者同时发布了 3 个恶意版本,覆盖了 node-ipc 的两条主要版本线:

1
2
3
[email protected]   ← 9.x 版本线(伪造,此前从未有 .cjs 入口文件)
[email protected]   ← 9.x 版本线(伪造)
[email protected]  ← 12.x 版本线

这意味着使用以下版本范围的项目都会自动拉取到恶意版本:

1
~9.1.x, ~9.2.x, ^9, ^12, ~12.0

9.x 版本是完全伪造的。攻击者直接复制了 12.x 的包结构,注入恶意代码后发布为 9.x。即使你锁定了 ^9.1.5,也会被升级到恶意的 9.1.6

恶意代码注入方式

攻击者没有修改源代码,也没有添加 preinstall/postinstall 生命周期脚本。他们选择了一种更隐蔽的方式:

直接在编译后的 CommonJS 入口文件 node-ipc.cjs 末尾追加 80KB 混淆代码:

1
2
3
4
5
var singleton = new IPCModule();
0 && (module.exports = { IPCModule });

// 80KB 混淆恶意代码(IIFE,加载即执行)
+(function(_0xaed59b, _0x282d65) { ... })();

这种注入方式有 4 个关键优势:

  • 加载即执行——require('node-ipc') 时 Node.js 自动执行所有顶级语句,无需调用任何方法
  • 绕过安全工具——多数工具只扫描生命周期脚本,不检查代码内容
  • 不影响正常功能——恶意代码在后台运行,应用程序表现完全正常
  • ESM 项目不受影响——只修改了 .cjs 入口,.js(ESM)入口未被篡改

混淆技术:自定义 Base‑16 密码

80KB 的恶意代码经过深度混淆:

  • 所有字符串转为十六进制编码
  • 自定义解码函数在运行时解密
  • 控制流平坦化 + 死代码插入
  • C2 服务器地址 sh.azurestaticprovider.net 在静态分析中完全不可见

攻击执行流程(6 个阶段)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
阶段1: 模块加载触发 IIFE
  ↓ require('node-ipc') 自动执行
阶段2: 配置解码
  ↓ 从硬编码字符串表解压 C2 地址、认证密钥等
阶段3: 目标门控(仅 12.0.1)
  ↓ 计算当前文件路径 SHA‑256,与硬编码哈希比对
  ↓ 非目标系统静默退出(精准打击,降低被发现概率)
阶段4: 守护进程化
  ↓ fork 子进程,设置 __ntw=1 环境变量
  ↓ 删除 NODE_OPTIONS(移除调试标志)
  ↓ 父进程继续正常执行,子进程后台运行
阶段5: 系统枚举与凭证窃取
  ↓ 扫描 90+ 类文件路径,跳过 >4MB 文件和 .git/node_modules
  ↓ 打包为 tar.gz
阶段6: 双通道数据外传
  → 通道1: HTTPS POST 到 sh.azurestaticprovider.net:443
  → 通道2: DNS TXT 查询隧道(直接到 C2 的 DNS,绕过公共 DNS 日志)

窃取目标清单(90+ 类)

类别目标文件
云平台~/.aws/credentials~/.azure/accessTokens.json~/.config/gcloud/
SSH/Git~/.ssh/id_rsa~/.git-credentials~/.config/gh/hosts.yml
Kubernetes~/.kube/config~/.docker/config.json、K8s service account token
AI 工具.claude.json~/.claude/mcp.json.kiro/settings/mcp.json
IaC~/.terraform.d/credentials.tfrc.json**/terraform.tfvars
开发者~/.npmrc~/.pypirc~/.netrc
数据库~/.pgpass~/.my.cnf~/.snowflake/connections.toml
Shell~/.bash_history~/.zsh_history~/.python_history
环境变量.env.env.local.env.production

值得注意:AI 工具配置(.claude.json、MCP 配置)首次被列为供应链攻击的窃取目标,表明 AI 编程工具的凭证安全已经进入攻击者视野。

DNS 隧道外传:为什么极难检测

攻击者没有使用传统的 HTTP POST,而是采用了 DNS TXT 查询隧道:

1
2
3
4
1. 用 Google DNS (8.8.8.8) 解析 sh.azurestaticprovider.net → 获取 C2 IP
2. 创建自定义 DNS 解析器,直接查询 C2 IP(绕过系统 DNS)
3. 将压缩数据分块 → 十六进制编码 → 作为 DNS TXT 查询的子域名
4. 发送类似 <encoded-data>.bt.node.js 的 TXT 查询

为什么难以检测:

  • 绕过公共 DNS 日志——查询直接发到 C2,不经过公共 DNS 解析器
  • 绕过防火墙——大多数企业允许出站 DNS(UDP 53),因为这是互联网正常运行所必需的
  • 看起来像正常流量——DNS TXT 查询是合法的 DNS 记录类型

12.0.1 的精准打击机制

12.0.1 版本包含一个特殊的目标门控(9.x 版本没有):

1
2
3
4
5
6
7
8
const TARGET_HASH = 'bf9d8c0c3ed3ceaa831a13de27f1b1c7c7b7f01d2db4103bfdba4191940b0301';

const isTarget = !!module.filename &&
  crypto.createHash('sha256')
    .update(path.normalize(module.filename).toLowerCase(), 'utf8')
    .digest('hex') === TARGET_HASH;

if (!isTarget) return; // 非目标系统静默退出

这意味着:

  • 攻击者预先计算了目标系统的文件路径哈希
  • 只有匹配的系统才会执行完整恶意负载,其余系统(包括安全研究人员的沙箱)会静默退出
  • 极大降低了被发现的概率,保护了攻击基础设施

影响评估

直接影响

  • 69 万+ 次下载意味着大量项目已引入恶意代码
  • CI/CD 流水线和内部镜像仓库可能已缓存恶意包
  • 企业需要紧急轮换所有可能被窃取的凭证

间接影响

  • 开源信任危机——一个过期域名就能劫持千万级下载量的包
  • 休眠账号风险暴露——项目维护者中可能有大量多年未活跃但仍有高权限的账号
  • AI 工具安全进入攻击者视野——.claude.json 等 AI 工具配置首次被列为窃取目标

与 2022 年事件的对比

维度2022 年 peacenotwar2026 年供应链投毒
发起者原作者本人外部攻击者
动机政治抗议经济利益
技术手段直接修改源代码休眠账号劫持 + 混淆注入
影响范围有限(破坏性明显)极大(隐蔽性强)
数据外传HTTPS + DNS 隧道双通道

检测与应急

如何检查是否受影响

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 检查项目依赖
npm ls node-ipc

# 检查 package-lock.json 中的版本
grep -A2 '"node-ipc"' package-lock.json

# 检查全局安装
npm list -g node-ipc

# 检查 node_modules 中的实际版本
find . -path "*/node_modules/node-ipc/package.json" -exec cat {} \; | grep version

如果已受影响

  1. 立即轮换所有凭证——云平台 API Key、SSH 密钥、数据库密码、AI 工具 API Key
  2. 删除恶意版本——npm uninstall node-ipc 或手动删除 node_modules/node-ipc
  3. 清理 CI/CD 缓存——内部 npm 镜像、Docker 层缓存、构建产物
  4. 审计 Git 历史——检查是否有恶意版本被提交到代码仓库
  5. 检查环境变量——恶意代码会扫描 .env 文件和环境变量

安全版本

1
2
3
# 安全版本(5月14日前的最后已知安全版本)
[email protected]   ← 9.x 安全版本
[email protected]  ← 12.x 之前的安全版本

防御建议

短期(立即执行)

  • 锁定依赖版本——使用 npm ci + package-lock.json,禁用 ^~ 范围
  • 启用 npm 签名验证——npm config set sign-git-tag true
  • 定期运行 npm audit——集成到 CI/CD 流水线
  • 使用 Socket.dev——实时检测 npm 包中的可疑行为

中期(本周内)

  • 审查项目维护者账号——检查是否有休眠账号仍有发布权限
  • 清理 npm 缓存——npm cache clean --force
  • 轮换敏感凭证——尤其是 AI 工具的 API Key
  • 配置 DNS 出站监控——检测异常的 TXT 查询

长期(架构层面)

  • 采用 npm provenance——验证包的构建来源
  • 实施最小权限原则——CI/CD 中的 npm token 限制发布权限
  • 使用 lockfile‑lint——验证 lockfile 的完整性和来源
  • 建立供应链安全审计流程——定期审查依赖树

行业反思

核心问题:开源安全的"域名级单点故障"

这起事件暴露了 npm 生态一个根本性的安全缺陷:

一个维护者的邮箱域名过期 → 一个千万级下载量的包被劫持 → 69 万个项目被感染

这不是技术问题,而是治理问题。npm 的账号恢复机制依赖邮箱,而邮箱依赖域名。域名过期这个看似微不足道的事件,可以引发灾难性的连锁反应。

需要改变的

  • npm 应强制要求 2FA——尤其是高下载量包的发布操作
  • 休眠账号应自动降权——长期未活跃的维护者不应保留发布权限
  • 域名过期应触发告警——与包管理平台关联的邮箱域名应有监控机制
  • AI 工具凭证需要独立保护——.claude.json 等配置文件应加密存储

参考资料

  • StepSecurity: Active Supply Chain Attack: Malicious node-ipc Versions Published to npm
  • Socket.dev: node-ipc supply chain attack analysis
  • CSDN: node-ipc 2026 供应链投毒全解析
  • Anavem: Node‑ipc npm Package Compromised in Supply Chain Attack on npm

作者:小米 | 生成时间:2026-05-28 23:51 CST
模型:xiaomi-coding/mimo-v2.5-pro

原文链接: https://www.17you.com/programming/node-ipc-supply-chain-attack-analysis/ 已复制!
编程和技术

寻找技术支持帮助和技术合伙人一起搞事。

请点击联系我