软件供应链安全:风险与最佳实践
作者:Ann-Anica Christian
现代软件建立在你无法完全掌控的层之上——开源库、第三方管道、外部注册表。当恶意代码抵达用户时,它看起来完全合法。这就是软件供应链问题。本文拆解它是什么、在哪里失效,以及如何保护它。
保护软件供应链:关键风险、威胁与防范
什么是软件供应链?
软件供应链是参与构建和交付软件的每一个工具、系统、人员和流程——从第一行代码到最终用户设备。它不只是代码,而是代码触及的一切。
这超出了传统的软件开发生命周期(SDLC),SDLC 关注软件如何构建和部署,而供应链包含其周围的一切——依赖、构建系统、签名与分发。
在实践中,它涵盖:
- 源代码仓库——开发者推送和管理代码的地方,访问控制在此要么守住要么失守
- 开源库与依赖——添加到项目中的外部包,数量往往达数百
- CI/CD 管道——编译、测试和打包代码以发布的自动化系统
- 制品存储与包注册表——构建产物在分发前存储的地方
- 代码签名与发布流程——为分发准备和认证软件的机制
- 部署渠道——云平台、应用商店、企业环境和更新服务器
- 更新机制——向用户推送补丁和新版本的系统
当今典型的 SaaS 应用引入了约 203 个直接依赖和超过 1,200 个传递依赖。大多数团队对它们缺乏可见性。
关键洞察在于:如果攻击者攻陷该链条中的任何一环,他们无需直接攻破你的应用。他们可以在上游某处注入恶意代码,然后让你的系统自行打包和分发——它到达用户时看起来完全合法。这正是供应链攻击如此严重、如此可扩展的原因。
什么是软件供应链安全,为什么重要
软件供应链安全是保护参与构建和交付软件的一切——代码、依赖、构建管道和发布流程——的实践。它检查在开发和最终用户之间的任何阶段是否遭到篡改、攻陷或替换。
重点在于几个核心方面:
- 验证代码在任何阶段是否未被意外更改
- 确认软件确实来自其声称的发布者
- 保护构建系统和发布基础设施免受未授权访问
- 防止管道中任何环节的修改
- 确保用户通过可信渠道收到未被篡改的软件
许多团队将此与应用安全混淆,两者相关但不相同。应用安全处理运行中的应用内部漏洞——注入缺陷、失效的身份认证、配置错误的访问控制。供应链安全则早一步。它问的是:软件在到达这里之前是否被篡改过?
要可靠回答这个问题,需要落实几个基础事项。
当软件被数字签名时,它携带来源与完整性证明。签名过程使用非对称加密——私钥签署制品,相应公钥验证它。如果软件在签名后发生任何更改,签名就会失效。该模型建立在更广泛的公钥基础设施(PKI)之上,确保跨系统可验证信任而无需暴露私钥。
系统之间的通信——仓库、构建服务器、制品存储、部署环境——都需要加密。不仅是面向外部的流量,内部流量也是如此。许多入侵并非因为边界失效,而是因为内部系统彼此过于轻信。
签名密钥本质上就是你的软件发布者身份。如果有人获得它们,就能制作看似来自你的恶意软件——已签名、受信任,并通过你自己的渠道分发。在高保证环境中,这种保护通过硬件安全模块(HSM)强制执行,它将密钥与通用系统访问隔离,即使基础设施被攻陷也能防止密钥被提取。
过期证书、手动轮换的密钥和不一致的签名实践都是攻击者利用的运维缺口。自动化使这一切保持一致,无需依赖人的记忆。这通常通过证书生命周期管理系统来处理,自动化跨环境的签发、续订、轮换和吊销。
让我们基于这些系统在真实环境中的实际行为,拆解通常在哪里出错。
软件供应链中的关键组件与风险
源代码与仓库
你的仓库常被视为"唯一可信源"。这正是它成为目标的原因。
常见风险包括:
- 通过被攻陷的开发者账户进行未授权提交
- 通过钓鱼、令牌泄露或不安全存储导致的凭据窃取
- 内部篡改,比外部攻击更难检测、留下的痕迹更少
第三方与开源依赖
现代软件严重依赖外部库。有时达数百个。
问题在于你无法完全控制它们。此处风险包括:
- 故意发布到公共注册表的恶意包
- 依赖混淆攻击,攻击者上传与内部依赖同名但版本号更高的包,诱骗构建系统拉取恶意版本
- 深埋在依赖树(传递依赖树)中的隐藏漏洞——你的直接依赖所依赖的包,你可能从未显式审查过
Log4Shell(CVE-2021-44228)就是这里的典型例子。Log4j 作为传递依赖嵌入数百万应用。当该漏洞被发现时,大多数组织甚至无法快速判断是否暴露——因为他们对自己完整的依赖树缺乏可见性。
构建系统与 CI/CD 管道
CI/CD 管道是一切汇聚之处。代码在此被编译、测试、打包,并为发布做准备。如果这一层被攻陷,攻击者就获得非常有利的位置。
典型风险:
- 在构建期间修改代码的被攻陷构建环境
- 注入到管道步骤中的恶意脚本
- 环境变量或日志中暴露的令牌或凭据
SolarWinds 是教科书式例子。攻击者渗透供应商的构建环境,在已签名的 Orion 更新中插入后门,下游客户将其作为例行维护版本安装。
代码签名与发布完整性
这是关键的信任点之一。数字签名的软件告诉用户"这来自我们,且未被更改"。但如果签名过程薄弱,或密钥暴露,该信任就会崩塌。这正是理解什么是代码签名证书及其工作原理变得重要的地方,因为整个信任模型取决于该签名如何创建和验证。
风险包括:
- 被盗或暴露的签名密钥
- 软件在未经过适当签名验证的情况下发布
- 薄弱或缺失的发布者身份检查
已签名的恶意软件远比未签名的危险。用户和系统默认信任它。这就是为什么保护私钥是不可妥协的。
软件分发与更新
即使上游一切安全,分发仍可能是薄弱点。
常见风险:
- 拦截下载的中间人攻击
- 被篡改的更新包
- 过期或管理不善的信任证书
更新机制尤其敏感。如果攻击者攻陷它们,就能大规模向用户直接推送恶意更新。而且因为更新是预期中的,用户很少质疑。
五大软件供应链威胁
这些不仅是边缘案例,而是真实事件中反复出现的模式。有些一次就影响了数千家组织。
依赖混淆
研究员 Alex Birsan 在 2021 年演示了这一点:如果攻击者向公共注册表发布一个包,其名称与某组织的内部包相同但版本号更高,许多构建系统会自动拉取公共的恶意版本而非内部版本。不会触发警报,也没有明显迹象。只是恶意代码悄悄进入你的应用。
被攻陷的代码签名密钥
如果攻击者访问你的签名密钥,他们无需绕过安全检查。他们成为受信任的发布者。用合法密钥签名的恶意软件往往畅通无阻地通过终端防护和用户信任检查。损害不仅是技术上的,更是声誉上的。每个信任你软件的用户都信任了攻击者。
CI/CD 管道入侵
构建服务器是诱人目标,因为它们处于管道的中心点。一旦被攻陷,攻击者可以:
- 向构建中注入代码
- 在发布前修改制品
- 访问秘密和凭据
而且由于构建是自动化的,恶意更改能快速传播。
恶意开源组件
有时攻击者向流行库贡献后门。其他时候,他们创建看似有用、随时间获得采用度的包。棘手之处在于这些组件往往看起来合法。当问题被发现时,它们可能已被广泛使用。
2024 年的 XZ Utils 后门(CVE-2024-3094)将此推向极端——一个名为"Jia Tan"的匿名行为者花费约两年时间通过合法贡献赢得维护者信任,然后插入针对 OpenSSH 的 CVSS 10.0 后门。发现是偶然的:一位微软工程师在性能测试期间注意到异常的 500 毫秒 SSH 延迟并展开调查。
证书管理不善
过期证书不仅导致中断——它们破坏了用户和系统依赖以验证软件真实性的证书信任链。管理不善或存储不当的私钥导致更糟的后果:它们允许未授权实体冒充合法软件源、签名恶意软件并通过可信渠道分发。
软件供应链安全最佳实践
没有单一控制能保护软件供应链。每个阶段都引入自己的信任边界,任何一点的弱点都可能被携带并作为合法软件分发。
对所有软件发布进行数字签名
每次发布都应签名——毫无例外。数字签名保证:
- 软件在构建后未被更改
- 发布者可被验证
- 用户和系统可以信任他们正在安装的内容
未签名的软件,尤其是在企业环境中,正越来越被默认视为可疑。
使用安全存储保护签名密钥
签名密钥绝不应存放在明文文件或松散保护的系统中。使用加固的存储方案,例如:
- 用于最高保证环境的硬件安全模块(HSM)
- 基于云的密钥管理服务(AWS KMS、GCP KMS、Azure Key Vault)
- 对每次密钥使用都有审计日志的受控访问环境
访问应严格限制并受监控。如果密钥暴露,假定已遭攻陷并立即轮换。
实施 SBOM
软件物料清单(SBOM)是软件中每个组件的完整清单——可将其视为内部成分的营养标签。自美国第 14028 号行政命令要求联邦软件采购提供 SBOM,且欧盟《网络韧性法案》将其作为市场准入要求以来,SBOM 已从"锦上添花"变为许多场景下的监管基线。
实际价值立竿见影:当新漏洞披露时,SBOM 让你立即回答"我们是否受影响?",而不是花数天手动排查。Log4Shell 比任何白皮书都更有力地证明了这一点。两种主导格式被广泛使用:
- CycloneDX——OWASP 标准,聚焦安全,在工具中广泛支持
- SPDX——ISO 标准,在许可元数据方面更强,2024 年更新至 v3.0
Syft 和 Grype 等工具可以作为现有 CI 管道的一部分生成和消费 SBOM。
采用供应链安全框架
框架为你提供了一种结构化的方式来思考成熟度和优先级。SLSA(软件制品供应链级别,由 Google 开发)提供四级构建完整性和溯源跟踪。使用托管构建服务,大多数团队可在两到四周内达到 SLSA Level 2,且本可让 SolarWinds 式构建篡改变得可检测。NIST SP 800-204D 提供与联邦要求对齐的补充性 CI/CD 安全指导。
保护开发管道中的通信
数据在系统、仓库、构建服务器、制品存储和部署环境之间不断流动。所有这些都需要加密。不仅是外部通信,内部流量也是如此。
自动化证书生命周期管理
手工处理证书扩展性不佳。自动化证书签发、续订和轮换、按需吊销,有助于避免因证书过期或管理不善导致的停机和安全缺口。它还减少对人工干预的依赖——错误往往就在这里产生。
监控与验证依赖
你无需停止使用开源——当 98% 的现代代码库都包含它时这不现实。但你需要可见性。这意味着:
- 知道你正在使用哪些依赖以及它们来自哪里
- 在 CI 管道中运行软件成分分析(SCA)
- 使用哈希验证固定依赖版本,而不是拉取"最新"
- 使用内部包镜像或经审核的注册表以减少对恶意包的暴露
OpenSSF Scorecard 值得一提——它为开源项目跨 18 项检查提供自动化的安全健康度量,帮助团队在添加依赖之前评估其风险。
在构建环境中强制执行最小权限访问
构建系统往往拥有超出实际所需的访问权限。限制它:只有所需资源才可访问,秘密应被严格限定范围,签名密钥和凭据绝不应在管道各阶段广泛暴露。如果出了问题,爆炸半径仍是可控的。
速查:最佳实践一览
| 最佳实践 | 应对的威胁 | 工具示例 |
|---|---|---|
| 对所有发布签名 | 被篡改的分发 | Sigstore、cosign、DigiCert |
| 安全密钥存储 | 签名密钥泄露 | AWS KMS、Azure Key Vault、HSM |
| 实施 SBOM | 隐藏的依赖漏洞 | Syft、Grype、CycloneDX、SPDX |
| 采用 SLSA 框架 | 构建篡改 | Sigstore、GitHub Actions provenance |
| 加密管道流量 | 中间人攻击 | TLS、双向 TLS、VPN |
| 自动化证书生命周期 | 过期证书 / 信任缺口 | ACME、Venafi、HashiCorp Vault |
| 持续 SCA 扫描 | 恶意 / 易受攻击依赖 | Grype、Snyk、Dependabot、Trivy |
| 最小权限访问 | CI/CD 管道入侵 | OIDC、短期令牌、Vault |
结论
软件供应链攻击看起来不像攻击。这正是它们奏效的原因,也是为什么仅靠边界安全和运行时防护是不够的。保护供应链意味着在每个阶段构建可验证的信任。
监管方向是明确的。第 14028 号行政命令、欧盟《网络韧性法案》和 CISA 的 2025 年 SBOM 指导都指向将供应链透明度作为基线要求。对于仍将其视为可选项的组织,问题不是供应链事件是否会发生,而是当发生时他们是否有可见性知道它发生了。
延伸阅读:
- 为什么我应该在发布前对代码签名并验证?
- 你的代码签名证书已过期——现在怎么办?