2020年12月13日,美国网络安全公司FireEye发布了一份震动全球的安全公告。该公司在调查自身安全事件时,发现了一个潜伏已久的高级持续性威胁(APT):攻击者通过入侵网络监控软件供应商SolarWinds,在其产品更新中植入了后门。这个被命名为SUNBURST的恶意软件,随着正常的软件更新被推送给了约18,000家客户——包括美国财政部、国土安全部、国家安全局,以及微软、英特尔、思科等全球顶级科技公司。

这不是一次普通的入侵。攻击者没有选择直接攻击目标组织,而是瞄准了目标组织信任的软件供应商。当18,000台服务器从SolarWinds下载"安全更新"时,它们同时下载了攻击者的入场券。

这种攻击模式被称为软件供应链攻击(Software Supply Chain Attack)。它的可怕之处在于:攻击者只需污染一个上游组件,就能像传染源一样将恶意代码传播到下游的每一个角落。在开源组件占据现代软件开发绝对主流的今天,软件供应链已经成为网络攻击者最垂涎的目标。

一个被低估的攻击面

2021年,安全研究员Alex Birsan做了一次令人震惊的实验。他发现许多科技巨头的内部代码仓库中,package.jsonrequirements.txt文件会引用一些不存在于公共包仓库的"私有包名"。一个想法浮现:如果他在npm、PyPI或RubyGems上抢先注册这些名字,会发生什么?

结果超出了所有人的预期。通过上传带有DNS回连功能的"恶意"包,他成功渗透了超过35家大型科技公司的内部网络,包括苹果、微软、贝宝、特斯拉、优步等。苹果在几小时内就自动安装了他上传的包;Shopify的构建系统同样中招。Birsan为此收获了超过13万美元的漏洞赏金——包括苹果、微软、Shopify各自给出的30,000美元最高奖励。

这个被称为依赖混淆攻击(Dependency Confusion)的技术揭示了一个残酷的事实:现代软件开发中,pip installnpm install这样的命令正在被盲目信任。包管理器在解析依赖时,会同时查询内部私有仓库和公共仓库,然后选择版本号更高的那个——攻击者只需上传一个版本号极高的恶意包,就能劫持整个构建流程。

开源生态:攻击者的狩猎场

软件供应链攻击并非SolarWinds事件后才出现的新现象。根据ReversingLabs整理的历史记录,可追溯至1982年的跨西伯利亚管道爆炸事件——据称是美国CIA在控制软件中植入逻辑炸弹的结果。但真正让这类攻击走入主流视野的,是开源生态系统的爆发式增长。

今天,一个典型的现代应用程序可能依赖数百个第三方组件。一个简单的Node.js项目,其node_modules目录动辄包含上千个子目录。这些依赖的依赖(传递依赖)构成了一个庞大的信任网络——但开发者往往只审查直接依赖,对传递依赖几乎一无所知。

Typosquatting:打字错误的代价

2018年11月,安全研究人员发现npm上有一个名为flatmap-stream的恶意包被添加到了流行的event-stream包的依赖列表中。这个恶意包专门针对Copay比特币钱包,在特定条件下会窃取用户的钱包私钥。更令人不安的是,event-stream的原始维护者已经将包的控制权转让给了一个陌生人——攻击者通过伪装成热心贡献者,获得了在流行包中注入恶意代码的机会。

这只是冰山一角。Typosquatting(拼写劫持)是一种更简单、更隐蔽的攻击方式:攻击者注册与热门包名相似的名字,等待粗心的开发者输错字符。react变成了ractlodash变成了lodshrequests(Python)变成了request。当开发者匆忙敲下键盘时,一次小小的打字错误就可能让攻击者获得其系统的完整访问权限。

2024年3月,PyPI遭遇了一场大规模typosquatting攻击:超过500个恶意包被上传到仓库,针对流行的机器学习库(如tensorflowtorchrequests)进行拼写劫持。攻击规模之大迫使Python软件基金会暂停了新用户注册和新项目创建。

维护者账号劫持:从信任链条的顶端入手

2025年9月8日,npm生态系统遭遇了有史以来最大规模的供应链攻击。攻击者通过钓鱼邮件成功劫持了一名维护者的npm账号,随后发布了18个广泛使用的核心包的恶意版本——包括chalkdebugansi-styles等数十亿周下载量的基础库。

这次攻击的精妙之处在于:攻击者没有创建新包,而是直接篡改了现有可信包的发布版本。这绕过了开发者可能进行的"包名是否可疑"检查——chalkdebug是任何Node.js开发者都熟悉的老朋友,它们的版本更新几乎不会被质疑。

影响范围难以估量。这些包是JavaScript生态的基础设施,被数百万个项目直接或间接依赖。当恶意代码随着正常的npm update流入全球开发者的机器和CI/CD流水线时,攻击者已经获得了在这些环境中执行任意代码的能力。

SolarWinds:供应链攻击的教科书

如果说npm投毒事件展示了开源生态的脆弱性,那么SolarWinds攻击则证明了供应链攻击可以具有国家级威胁的规模和复杂度。

攻击者(普遍认为是俄罗斯对外情报局SVR支持的APT29,又称Cozy Bear)的入侵始于2019年9月,他们首先获得了SolarWinds内部网络的访问权限。随后,攻击者花了数月时间研究SolarWinds的构建系统——最终找到了完美的注入点:在Orion平台的软件更新编译过程中插入恶意代码。

植入的SUNBURST后门设计极其精妙:

休眠机制:恶意代码在首次到达目标系统后会静默等待12-14天,然后才开始任何通信。这有效规避了沙箱检测和短期监控。

多阶段C2通信:SUNBURST使用DNS协议作为第一层通信信道,通过解析特定子域名来确认目标是否值得进一步渗透。只有当解析结果满足特定条件(IP地址位于特定范围)时,才会激活第二阶段HTTPS通信。

高度选择性:在对1460个子域名的被动DNS解析记录分析中,研究者发现只有一个真正激活了后门的第二阶段。这意味着攻击者预先筛选了目标,只对特定组织(如政府机构、关键基础设施运营商)进行后续渗透。

防御规避:后门会检测安全软件(如杀毒软件、EDR)的存在,并在检测到时自我禁用。它还会检查是否在沙箱或分析环境中运行,避免暴露真实行为。

这次攻击的影响持续了八个月才被发现。期间,攻击者不仅窃取了敏感数据,还在部分目标的网络中部署了更深入的后门,为长期潜伏创造条件。即使SolarWinds发布了修复版本,受害者也可能在毫不知情的情况下继续被监控。

攻击向量的完整图景

2022年,SAP安全研究团队联合学术界发表了题为《Taxonomy of Attacks on Open-Source Software Supply Chains》的系统化知识(SoK)论文。通过对183篇学术论文和安全报告的分析,他们构建了一个包含107种攻击向量的攻击树,并将它们映射到94个真实世界事件。

这个分类体系揭示了供应链攻击的三个核心维度:

与现有包的干扰程度

  • 从零创建全新恶意包(需要推广以吸引受害者)
  • 创建与合法包名相似的包(typosquatting、combosquatting等)
  • 篡改现有的合法包(需要先获得访问权限)

攻击发生的供应链阶段

  • 源代码阶段(提交恶意合并请求、利用Unicode字符隐藏恶意代码)
  • 构建阶段(入侵构建系统、污染CI/CD流水线)
  • 分发阶段(劫持包仓库、中间人攻击、DNS缓存投毒)

涉及的利益相关者

  • 贡献者(提交恶意补丁)
  • 维护者(账号被劫持或主动恶意)
  • 系统管理员(基础设施被入侵)
  • 下游消费者(安装恶意依赖)

攻击者可以根据目标选择最适合的攻击路径。想要大规模撒网?typosquatting成本低、可扩展性强。想要精准打击高价值目标?入侵特定项目的构建系统或维护者账号。想要国家级影响?SolarWinds已经证明了可能性。

信任的代价:为什么供应链攻击如此致命

传统安全模型假设存在一个清晰的边界:组织内部的系统和外部的威胁。防火墙、入侵检测系统、访问控制策略都在这个假设下设计。但软件供应链攻击打破了这一假设。

当代码来自受信任的来源时,它往往被授予与内部代码相同的权限。npm install下载的代码会被执行,CI/CD流水线会运行它,开发者的机器会安装它——而且所有这一切都发生在安全边界内部。攻击者不需要突破防火墙,他们只需要让受害者主动下载恶意代码。

更深层的问题在于信任的传递性。开发者信任npm仓库;npm信任包的维护者;维护者可能信任活跃的贡献者;贡献者可能信任第三方库的作者……这条信任链可以延伸很远,而链条上的任何一个环节被攻破,整个信任体系就会崩塌。

2021年12月,Log4j远程代码执行漏洞(CVE-2021-44228,即Log4Shell)被披露。这个漏洞的严重性不仅在于其技术影响(CVSS评分10.0/10),更在于其供应链效应。Log4j是一个基础的Java日志库,被数不清的开源项目和企业应用作为传递依赖使用。许多组织甚至不知道自己的系统中包含Log4j——它可能隐藏在某个第三方库的依赖树深处。

这就是传递依赖风险的本质:你信任的直接依赖,可能引入了你完全不熟悉的间接依赖。当这些间接依赖出现安全问题时,你可能根本不知道自己受到影响。

防御的演进:从被动响应到主动证明

面对软件供应链攻击的严峻形势,业界正在构建多层次的防御体系。

SLSA框架:供应链安全的标准化路径

Supply-chain Levels for Software Artifacts(SLSA,读作"salsa")是由Google主导、OpenSSF推动的安全框架。它的核心思想是为软件制品定义一组渐进式的安全等级,从基础的构建过程文档化开始,最终达到可验证的构建完整性。

SLSA定义了四个等级:

  • 等级1:构建过程有文档记录,包括构建命令、输入源、输出制品等元数据
  • 等级2:使用托管构建服务,版本控制可追溯
  • 等级3:构建环境隔离,构建定义不可变,构建参数可审计
  • 等级4:两方验证(需要两个独立的构建者同意),封闭构建(没有网络访问)

SolarWinds攻击后,该公司就采用了类似SLSA等级3的安全实践,包括可复现构建和隔离构建环境。这意味着如果攻击者再次尝试在构建过程中注入代码,差异检测机制会触发警报。

SBOM:软件的物料清单

Software Bill of Materials(SBOM)的概念借鉴自制造业——就像产品包装盒上的成分列表,SBOM列出了软件中包含的所有组件及其版本信息。

2021年,美国国家标准与技术研究院(NTIA)发布了SBOM最低要素规范,定义了必须包含的字段:

  • 供应商名称
  • 组件名称
  • 组件版本
  • 唯一标识符
  • 依赖关系
  • SBOM数据的作者
  • 时间戳

2025年8月,网络安全与基础设施安全局(CISA)更新了这一规范,增加了对自动化支持和流程实践的要求。

SBOM的价值在于:当某个组件被发现存在漏洞或恶意代码时,组织可以快速确定自己是否受影响、影响范围有多大。Log4j事件中,许多组织花了数周时间才完成受影响系统的盘点——如果有完善的SBOM,这个过程可以缩短到几小时甚至几分钟。

常见的SBOM格式包括SPDX(Linux基金会)、CycloneDX(OWASP)和SWID标签(ISO/IEC)。

Sigstore:无密钥签名的未来

传统代码签名存在一个核心痛点:密钥管理复杂。开发者需要安全地存储私钥、定期轮换、处理密钥泄露事件——这些操作对个人维护者来说往往过于繁琐,导致代码签名在实践中被忽视。

Sigstore项目试图通过"无密钥签名"(keyless signing)解决这一问题。其核心组件包括:

  • Fulcio:证书颁发机构,根据OpenID Connect身份(如GitHub账号)颁发短期有效的代码签名证书
  • Rekor:不可篡改的透明日志,记录所有签名事件,便于审计和监控
  • Cosign:命令行工具,用于签名容器镜像和其他制品

当开发者使用Sigstore签名时,他们不需要管理长期有效的私钥。签名过程通过OIDC身份验证(比如GitHub Actions的令牌)自动完成,生成的证书有效期仅约10分钟。签名记录被写入Rekor透明日志,任何人都可以验证签名的真实性。

这种设计大大降低了代码签名的门槛。目前,Kubernetes、TensorFlow、Distroless等知名项目已经开始使用Sigstore对其发布产物进行签名。

开发者的生存指南

对于身处一线的开发者来说,如何在日常工作中防范供应链攻击?以下是一些经过实践验证的建议:

依赖固定化:始终使用lock文件(package-lock.jsonyarn.lockpoetry.lock等)。这不仅确保构建的可复现性,也防止攻击者在包仓库上发布恶意的新版本后自动流入你的项目。更进一步,可以考虑固定到具体的哈希值而非版本号。

最小化依赖:在引入新依赖前,评估是否真的需要。许多"一行代码"的工具包(如is-oddis-even)看似方便,实则增加了不必要的攻击面。每个直接依赖都可能引入数十个间接依赖。

私有仓库:对于企业环境,使用私有包仓库镜像(如Artifactory、Nexus)可以提供额外的控制层。管理员可以审查和批准哪些包可以被内部团队使用,也能缓存特定版本防止上游变更影响下游。

启用多因素认证:如果你是开源项目的维护者,请务必为你的包仓库账号启用MFA。维护者账号劫持是最有效的攻击向量之一,而MFA可以显著提高攻击成本。

使用安全工具:集成软件成分分析(SCA)工具到CI/CD流水线中,自动检测已知漏洞和可疑包。一些工具(如Snyk、Socket、Dependabot)还能检测恶意代码模式和typosquatting尝试。

审查传递依赖:定期审计项目的完整依赖树。npm lspipdeptree等工具可以帮助你了解到底引入了什么。对于可疑的间接依赖,评估是否有更安全的替代方案。

一个尚未解决的悖论

软件供应链安全的根本悖论在于:开源软件的成功恰恰源于其开放性和低门槛。任何人都可以贡献代码、发布包、复用他人的工作——这种无摩擦的协作模式创造了现代软件工业的基石。但同样的开放性也意味着攻击者可以轻易加入这个生态系统,伺机而动。

SLSA、SBOM、Sigstore等框架和工具正在努力在开放性和安全性之间寻找平衡。但它们都要求额外的努力——对于资源充足的企业来说,这些是值得的投资;对于用爱发电的开源维护者来说,可能是不堪重负的负担。

更令人忧虑的是,攻击者的技术也在进化。2025年的npm攻击已经展示了AI辅助的钓鱼和社会工程能力;未来的攻击可能会利用AI生成更难检测的恶意代码、更逼真的伪装身份。

在可预见的未来,软件供应链攻击仍将是网络威胁景观中的重要组成部分。理解攻击者的战术、掌握防御者的工具、保持对依赖关系的警惕,是每一个参与软件开发的人必须具备的素质。

毕竟,在软件定义的世界里,供应链安全就是国家安全。


参考文献

  1. SolarWinds. (2021). New Findings From Our Investigation of SUNBURST. SolarWinds Blog.
  2. Birsan, A. (2021). Dependency Confusion: How I Hacked Into Apple, Microsoft and Dozens of Other Companies. Medium.
  3. Ladisa, P., Plate, H., Martinez, M., & Barais, O. (2022). SoK: Taxonomy of Attacks on Open-Source Software Supply Chains. IEEE S&P.
  4. Ohm, M., Plate, H., Sykosch, A., & Meier, M. (2020). Backstabber’s Knife Collection: A Review of Open Source Software Supply Chain Attacks. DIMVA.
  5. ReversingLabs. (2024). A (Partial) History of Software Supply Chain Attacks.
  6. OpenSSF. (2025). SLSA - Supply-chain Levels for Software Artifacts.
  7. NTIA. (2021). The Minimum Elements For a Software Bill of Materials (SBOM).
  8. CISA. (2025). 2025 Minimum Elements for a Software Bill of Materials (SBOM).
  9. Cynet. (2025). SUNBURST: Attack Flow, C2 Protocol, and Prevention.
  10. Wiz. (2025). Widespread npm Supply Chain Attack: Breaking Down Impact.
  11. Snyk. (2021). The Log4j vulnerability and its impact on software supply chain security.