跳转到内容
← 返回核心概念
安全与隐私计算机科学 · 软件与系统安全12 分钟阅读

软件供应链安全

Software Supply Chain Security

现代软件很少从空白开始。一个应用可能依赖操作系统镜像、编译器、包管理器、数百个直接与传递依赖、CI 插件、制品仓库、部署脚本和自动更新服务。攻击者不一定要攻破最终应用;只要控制其中一个被信任环节,就可能让合法流水线替自己分发恶意代码。 软件供应链安全研究的不是“依赖有没有 CVE”这一件事,而是从需求、源码、依赖、构建…

软件供应链SBOMSLSA来源证明安全构建

现代软件很少从空白开始。一个应用可能依赖操作系统镜像、编译器、包管理器、数百个直接与传递依赖、CI 插件、制品仓库、部署脚本和自动更新服务。攻击者不一定要攻破最终应用;只要控制其中一个被信任环节,就可能让合法流水线替自己分发恶意代码。

软件供应链安全研究的不是“依赖有没有 CVE”这一件事,而是从需求、源码、依赖、构建、签名、发布到部署的完整信任链:什么制品被允许进入生产,它是否来自预期源码和构建过程,谁批准了变化,以及事后能否重建证据。

破除误解:签名、SBOM 和扫描都不是安全证明

三个常见结论都过强:

  • “制品有签名,所以代码安全”:签名只证明持有某密钥者对这些字节签过名。若签名身份、构建器或私钥已被攻陷,恶意制品仍可拥有有效签名。
  • “有 SBOM,所以没有供应链风险”:SBOM 是组件清单。它可以支持漏洞响应,却不证明组件未被篡改、漏洞可达、配置安全或发布过程可信。
  • “扫描结果为零,所以可以上线”:扫描器只覆盖已知规则、可见依赖和当前数据库。业务逻辑后门、构建脚本、不可达判断错误与新漏洞可能不在结果里。

安全来自多层证据交叉约束,而不是购买一个工具后获得绿色徽章。

建立模型:资产、对手与信任边界

需要保护的资产包括源码完整性、发布权限、构建秘密、制品身份、更新通道、漏洞信息和用户环境。对手可能是:

  • 窃取维护者账户的外部攻击者;
  • 有提交权、CI 管理权或发布权的恶意内部人;
  • 控制包名、依赖项目或公共仓库的第三方;
  • 能修改构建环境、编译器、runner 镜像或网络响应的人;
  • 利用自动更新和大规模分发扩大影响的攻击组织。

典型信任边界沿流水线展开:

text
作者工作站
  → 源码托管与评审
  → 依赖解析
  → 构建平台
  → 制品仓库
  → 发布/更新服务
  → 部署环境
  → 运行时
```

每次跨边界都应有身份、完整性、授权和审计证据。仅保护 Git 仓库,却允许任何 CI job 使用长期生产密钥,等于把最强权限放在更弱的边界里。

攻击路径:供应链不是单一入口

环节典型攻击需要回答的问题
作者与评审账户接管、恶意提交、绕过评审谁提出、谁批准,是否分离职责
依赖选择typosquatting、dependency confusion、维护者接管包来自哪个命名空间,版本为何被选择
构建过程注入脚本、污染 runner、编译器后门构建是否隔离,输入是否完整记录
制品发布仓库凭据泄露、替换二进制下载的摘要、签名和来源证明是否匹配
更新通道回滚、冻结、镜像投毒是否验证版本新鲜度、授权角色与阈值
部署使用标签漂移、配置注入、默认凭据实际运行的是否是已批准摘要

SLSA 将重点放在源码完整性构建完整性:接受的源码是否表达生产者意图,制品是否由正确源码、依赖和构建配方生成。它不覆盖恶意生产者、运行时默认凭据和所有依赖可用性风险,因此不能把 SLSA 等级当成全系统安全等级。

第一层:保护源码与发布身份

源码控制的目标不是“所有人都用 Git”,而是让每个可发布变化有可追踪意图:

  • 对维护者和发布者使用抗钓鱼认证,避免共享账户;
  • 保护主分支和标签,要求评审、状态检查及关键路径所有者批准;
  • 把提交、合并、版本标签和发布动作分开授权;
  • 对高风险变化采用双人控制或短期提权;
  • 记录身份、时间、差异和策略版本,并保护审计日志本身。

签名提交可以增加来源证据,但无法证明评审质量,也无法阻止已被攻陷的维护者签恶意代码。身份系统和恢复流程应与 authentication-authorization 使用同一威胁模型。

第二层:约束依赖解析

锁文件和固定版本提高可重复性,但“锁定恶意版本”仍然不安全。依赖治理还需要:

  • 区分直接、传递、开发、构建与运行时依赖;
  • 限制允许的仓库和命名空间,防止内部包被公共同名包抢占;
  • 固定制品摘要,而不只依赖可移动标签;
  • 在受控环境评估 install hooks、编译脚本和代码生成器;
  • 记录许可证、维护状态、来源和替代方案;
  • 对升级做差异审查,而不是只看版本号和 CVE 数量。

依赖越少并不自动越安全,但每个依赖都会增加维护者、更新、构建和响应边界。选择依赖时应评估它减少的自研风险是否大于新增信任成本。

第三层:让构建产生可验证证据

理想构建平台应是隔离、短寿命、最小权限且从声明输入启动。构建结束后销毁 runner,避免上一任务残留污染下一任务;秘密只在需要的步骤短期提供,不写入日志或镜像层。

来源证明(provenance)记录制品摘要、源码修订、构建器身份、构建参数和依赖等信息。消费者不能只检查“有一份证明”,而要执行策略:

text
制品摘要是否匹配?
构建器是否在允许列表?
源码仓库与修订是否符合发布策略?
构建参数是否允许?
证明是否由受信身份签署且未过期?
```

可重复构建让独立构建者从同一声明输入得到相同输出,可用于发现未记录输入或构建污染。但时间戳、随机性、环境路径和编译器差异会破坏重现;即使成功重现,也只说明多个构建结果一致,不证明源码没有恶意逻辑。

第四层:SBOM、签名与透明日志

SBOM 至少应描述组件名称、版本、供应者、唯一标识和依赖关系,并与具体制品版本绑定。CISA 区分设计、源码、构建、分析和部署 SBOM;不同生成时点看到的组件不同。遗漏的传递依赖和“已知未知”必须显式表示。

签名验证需要同时验证:

  1. 制品摘要;
  2. 签名算法与参数;
  3. 证书或公钥链;
  4. 签名身份是否符合项目策略;
  5. 签名时间及撤销/透明日志证据。

Sigstore 用短寿命证书把临时签名密钥绑定到 OIDC 身份,并将签名事件写入 Rekor 透明日志。透明日志提高可发现性和事后审计能力,但需要监控;日志里出现一条签名记录,不代表签名内容经过安全评审。

第五层:安全分发与部署

更新系统还要抵抗旧版本回滚、镜像冻结、密钥轮换失败和单个在线密钥失陷。The Update Framework(TUF)通过角色分离、阈值签名、版本和过期元数据降低这些风险。

部署时应按不可变摘要引用镜像或包,验证签名和来源策略,再由准入控制决定是否运行。若生产最终仍使用 latest 标签,前面严格验证的可能是另一个制品。

运行时检测不能替代构建完整性,却能限制残余风险:最小权限、只读文件系统、网络分段、行为监测和快速回滚可以减少未知恶意行为的影响范围。

漏洞响应:清单只有在能行动时才有价值

新漏洞披露后,团队需要回答:

  1. 哪些源码、构建和部署制品包含受影响组件?
  2. 漏洞代码是否在当前配置和调用路径中可达?
  3. 是否存在运行时缓解,还是必须重建发布?
  4. 修复版本是否改变 API、行为或许可证?
  5. 如何证明替换制品来自正确修订和构建器?
  6. 哪些客户需要通知,旧制品何时撤销?

仅按 CVSS 自动阻断会产生误报和优先级拥塞;只看“当前不可达”又可能忽略配置变化。风险排序应结合可利用性、暴露、资产价值、修复成本和补偿控制,并记录判断依据。

一条可审计的最小闭环

text
受保护身份与评审
→ 固定且可追踪的输入
→ 隔离构建
→ SBOM + 来源证明
→ 身份绑定签名
→ 消费端策略验证
→ 按摘要部署
→ 运行监测与漏洞响应
```

NIST SSDF 将实践组织为准备组织、保护软件、生产良好保护的软件和响应漏洞。它提供共同词汇,不是认证徽章。成熟度应通过可重复证据衡量:随机抽取一个生产制品,团队能否在限定时间内追溯源码、依赖、构建器、批准者、部署位置和撤销路径。

跨域连接

  • 编译器:信任信任攻击的要点是编译器可以在自身源码不含后门的情况下持续复制后门,于是「审计源码即可」这一结论隐含了工具链可信的前提,而工具链本身也是被构建出来的制品。可重复构建与多样化双重编译正是针对这个前提设计的检验——它们不能证明源码无害,只能证明二进制确实来自那份源码。
  • 信息不对称:使用者无法直接观察上游的构建过程质量,只能观察下载量、星标、有无签名这些可见信号,于是市场结构接近柠檬市场——低质但信号好的包能挤占份额。这正好解释了正文那三条否定:物料清单、签名与扫描的作用是把不可观测的过程转成可核验的信号,而信号本身不等于质量。
  • 问责:可审计的最小闭环与公共行政的问责要求同构:谁在何时批准了什么必须能被独立复核,因此需要职责分离、双人控制,以及对审计日志本身的保护。推论是一条硬性的权限判据——同一个角色若既能签发又能删除审计记录,审计就等于不存在,这是权限设计问题,换工具解决不了。
  • 免疫系统:纵深防御与免疫的分层逻辑相同:每一层都假设上一层可能被突破,作用是限制扩散范围而非保证不被侵入。共享的还有失败模式——灵敏度提高若不伴随特异性提高,响应能力会被误报耗尽,正文说的按评分自动阻断造成优先级拥塞就是这种反应。可用的推论是漏洞排序必须结合可达性与暴露面。
  • 工作与劳动组织:关键依赖常由少数无报酬维护者支撑,于是攻击面集中在极少数个人账户上,接管一个账户即可影响大量下游。这把问题从技术挪到劳动结构上:使用是非竞争的,维护成本却由个人独自承担。推论是阈值签名与多维护者不是冗余设计,而是把单一自然人从信任链的必经之路上移开。

参考文献

  • NIST. Secure Software Development Framework (SSDF) Version 1.1. SP 800-218, 2022.
  • NIST. Cybersecurity Supply Chain Risk Management Practices for Systems and Organizations. SP 800-161 Rev. 1, 2022.
  • SLSA Community. Supply-chain Levels for Software Artifacts Specification v1.2. 2026.
  • CISA. Minimum Elements for a Software Bill of Materials. 2025.
  • CISA. Types of Software Bill of Material Documents. 2023.
  • The Update Framework. TUF Specification.
  • Sigstore. Security Model and Rekor Transparency Log Documentation.

延伸阅读

  • Wheeler, D. A. Fully Countering Trusting Trust through Diverse Double-Compiling. 2009.
  • Thompson, K. Reflections on Trusting Trust. Communications of the ACM, 1984.
  • OpenSSF. Scorecard and Supply Chain Integrity Working Group Resources.