供应链攻击

发布: (2025年12月30日 GMT+8 12:45)
5 min read
原文: Dev.to

请提供您希望翻译的完整文本(除源链接外的内容),我将按照要求将其翻译为简体中文并保留原有的格式。

Phase 1: 目标的解剖

在现代 Web 开发中,我们很少从头开始编写所有代码。我们站在 传递依赖 的肩膀上。

  • 直接依赖: 你安装 useful-auth-lib
  • 传递依赖: useful-auth-lib 依赖于 small-string-helper

隐藏的风险: 你的 package.json 里可能只有 10 个包,但 node_modules 文件夹中却包含 800 多个包。你的安全性仅与这 800 条链中最薄弱的一环一样强。

Phase 2: The Attack – “The Long Game”

1. Target Selection

攻击者不会盯上像 React 这样的大型库(太多人关注)。相反,他们会寻找一个 深层依赖——一个已经一年未更新、但被成千上万其他流行包使用的小型工具库。

2. Social Engineering (The “Trojan Horse”)

攻击者使用一个伪装成专业的 GitHub 账户,开始向仓库提交有帮助的、合法的代码。

  • 修正拼写错误。
  • 改进文档。
  • 优化循环。

结果: 原本工作负荷过重的维护者最终会授予他们 “Maintainer” 权限或发布到 npm 注册表的权限。

3. The Injection

攻击者发布了版本 v3.4.2。GitHub 上的代码看起来很干净,但发布到 npm registry.tgz 包含了恶意负载。

Key Insight: npm does not verify that the code in the .tgz file on their registry matches the code in the GitHub repository. This is where the backdoor lives.

第三阶段:执行流程

步骤 1:自动更新

大型金融科技公司的开发者运行常规命令:

npm update

由于 package.json 中的插入符号(^),例如 "small-string-helper": "^3.4.0",npm 会自动拉取恶意的 v3.4.2

步骤 2:生命周期钩子

攻击者利用 npm 生命周期脚本。在恶意包的 package.json 中加入:

{
  "scripts": {
    "postinstall": "node ./scripts/init.js"
  }
}

npm install 完成后,init.js 会自动以开发者或构建服务器相同的权限运行。

步骤 3:环境指纹识别

脚本不会立即发动攻击。它会“指纹”运行环境:

  • CI/CD 服务器? 检查 GITHUB_ACTIONSJENKINS_URL 等变量。
  • 高价值目标? 查找 .aws/credentials.env 文件或 id_rsa SSH 密钥。
  • 生产环境? 检查 NODE_ENV === 'production'

步骤 4:后门与数据泄露

如果条件满足,脚本会:

  • 向主应用代码注入片段,拦截登录表单。
  • 打开反向 shell,连接攻击者服务器,实现远程命令执行。
  • 窃取机密,将 .env 变量发送到远程 API。

第四阶段:现代防御策略

1. 依赖固定与锁文件

  • Lockfiles: 始终提交 package-lock.json。它强制使用确切的版本并验证包的哈希(完整性),以确保未被篡改。
  • Pinning: 对于高安全性项目,使用精确版本(例如 "library": "1.2.3")而不是范围(^1.2.3)。

2. 专业审计工具

工具功能
npm audit对已知 CVE 进行基础检查。
Snyk / Socket.dev分析代码的 行为(例如 “为什么这个 CSS 库会请求网络访问?”)。
StepSecurity监控 CI/CD 流水线,检测对未知 IP 地址的连接。

3. 网络隔离

在受限网络环境中运行构建过程。构建脚本 绝不应 需要向未知的外部 IP 地址发送数据。

4. SBOM(软件材料清单)

为每个发布生成 SBOM。这份对所使用的每个软件组件的完整清单,可帮助更轻松地判断新发现的漏洞是否影响到你。

要点

在 npm 的世界里,你不仅仅是在导入代码;你还在导入依赖树中每位开发者的安全实践。 依赖审计不是一次性任务;它是一个持续验证信任的过程。

Back to Blog

相关文章

阅读更多 »