引言:软件制品供应链等级SLSA(Supply-chain Levels for Software Artifacts)是由由谷歌发起,基于行业共识建立的一个逐步完善供应链安全的规范。本文基于Google SLSA框架来看软件供应链安全面临的安全风险。
1. 简介
2023 年 4 月,SLSAv1.0 发布,相比 SLSA v0.1 发生了很大的变化,该版本作为 SLSA 的第一个稳定版本,代表了广泛的共识,未来将不会发生重大变化。该框架为软件生产者和消费者提供了一套可遵循的标准,生产者可以遵循 SLSA 的指导方针使他们的软件供应链更安全,而消费者可以使用 SLSA 来决定是否信任软件包,组织通过遵循 SLSA 的指导,可以更好的确保其软件供应链的安全性和可靠性。
SLSA的目标是改善行业状态,尤其是开源,以防卫最紧迫的完整性威胁。使用SLSA,用户可以对他们使用的软件的安全态势做出明智的选择。
2. 软件面临的威胁
将软件从生产者传到消费者的过程中,SLSA定义了三大类(源代码威胁、依赖威胁、构建威胁)共计8个小类的威胁。
2.1. 源代码威胁
源代码完整性威胁是指对手可能引入不符合软件生产者意图的源代码更改。包括授权个体引入未经授权的更改。
Note: SLSA v1.0未解决源代码威胁,预计在未来的版本中会加以解决。
2.1.1. 提交未经授权的更改
敌手在没有任何特殊管理员权限的情况下通过官方源代码管理界面引入更改。
2.1.2. 妥协源代码仓库
敌手通过管理界面或对底层基础设施的妥协,向源仓库引入更改。
2.1.3. 从修改后的源码构建
敌手基于与官方源代码版本不匹配的源代码进行构建。
应对方法是将来源与对软件包的预期进行比较,这取决于SLSA构建L1的来源。
2.1.4. 从非官方代码构建
威胁: 使用预期的CI/CD流程,但从可能包含未经授权更改的非官方代码进行构建。
缓解措施: 验证器要求来源与预期值匹配。
示例: MyPackage应该从GitHub仓库good/my-package构建。但实际上,它从evilfork/my-package构建。
解决方案: 验证器拒绝,因为来源位置不匹。
2.1.5. 使用非官方分支或标签构建
威胁:使用预期的CI/CD流程和源位置,但检出了一个“experimental”分支或类似的分支,其中可能包含不打算发布的代码。
缓解措施:验证器要求溯源的源分支/标签与预期值匹配,或者源修订版本可从预期分支访问。
示例:MyPackage的发布版本是从main分支打的标签,该分支有分支保护。攻击者从不受保护的experimental分支构建,其中包含非官方更改。
解决方案:验证器拒绝,因为源修订版本无法从main分支访问。
2.1.6. 使用非官方构建步骤构建
威胁:使用正确的CI/CD平台构建软件包,但使用非官方的构建步骤。
缓解措施:验证器要求溯源的构建配置源与预期值匹配。
示例:MyPackage应该由Google Cloud Build使用源的cloudbuild.yaml文件中定义的构建步骤进行构建。攻击者使用Google Cloud Build进行构建,但使用通过RPC提供的自定义构建步骤。
解决方案:验证器拒绝,因为构建步骤不是来自预期的源。
2.1.7. 使用非官方参数构建
威胁:使用预期的CI/CD流程、源位置和分支/标签构建,但使用注入非官方行为的参数。
缓解措施:验证器要求溯源的外部参数都与预期值匹配。
示例1:MyPackage应该从release.yml工作流构建。攻击者从debug.yml工作流构建。
解决方案:验证器拒绝,因为工作流参数与预期值不匹配。
示例2:MyPackage的GitHub Actions工作流使用github.event.inputs允许用户为每次调用指定自定义编译器标志。敌对方设置了一个编译器标志,该标志覆盖了宏以向输出二进制文件中注入恶意行为。
解决方案:验证器拒绝,因为未预期的inputs参数。
2.1.8. 从检出后修改的代码版本进行构建
威胁:从检出后包含修改的代码版本进行构建。
缓解措施:构建平台直接从源代码库中拉取,并准确记录来源位置以进行溯源。
示例:敌手从MyPackage的源代码库获取,进行本地提交,然后从该本地提交请求构建。构建者记录了它没有从官方源代码库中拉取的事实。
解决方案:验证器拒绝,因为源代码库与预期值不匹配。
2.2. 依赖威胁
敌对方通过让制品引入其所需要功能的组件的行为。为了减少此类威胁,需要检查软件的SBOM清单,避免引入不安全的组件。
2.2.1. 使用危险的构建依赖项
威胁:敌手向构建制品所需的软件中注入恶意代码。
缓解措施:不适用 - 此威胁超出了SLSA v1.0的范围。可以通过固定构建依赖项(最好使用摘要而不是版本号)来减轻此威胁。
示例:制品使用libFoo并需要其源代码进行编译。敌对方破坏了libFoo的源代码库并插入了恶意代码。当软件包构建时,它包含了敌对方的恶意代码。
2.2.2. 使用危险的运行时依赖项
威胁:敌手向运行制品所需的软件中注入恶意代码。
缓解措施:不适用 - 此威胁超出了SLSA v1.0的范围。
示例:软件包动态链接到libBar并需要二进制版本才能运行。敌对方破坏了libBar的构建过程并插入了恶意代码。当您的制品运行时,它包含了敌对方的恶意代码。
2.3. 构建威胁
构建完整性威胁是指对于敌对方在不改变源代码的情况下向制品引入行为的潜在可能性,或者从软件生产者意图之外的源、依赖和/或过程进行构建。
当消费者根据预期验证软件包,确认他们收到的软件包是以预期方式构建的时,SLSA构建跟踪可以缓解这些威胁。
2.3.1. 破坏构建过程
敌对方通过篡改构建过程向构建输出引入未经授权的更改;或者向溯源中插入虚假信息。
这些威胁可以通过SLSA构建跟踪直接解决。
2.3.1.1. 伪造来源的值(构建L2+)
威胁:伪造虚假来源并让可信的控制平面对其进行签名。
缓解措施:在构建L2+阶段,可信的控制平面生成进入溯源的所有信息,除了(可选)输出软件包哈希。在构建L3+阶段,即使是决心的敌对方也无法破坏此过程。
示例1(构建L2):溯源在构建执行机上生成,而对手控制该机器。对手使用恶意进程使构建平台声称它是从源代码库good/my-package构建的,而实际上是从evil/my-package构建的。
解决方案:构建者在可信的控制平面上生成并签名溯源;执行机报告输出软件包,但对溯源没有其他影响。
示例2(构建L3):溯源在可信的控制平面上生成,但工作机可以打破容器以访问签名材料。
解决方案:构建者加强硬化以提供针对租户项目的强大隔离。
2.3.1.2. 伪造溯源的输出摘要
威胁:租户控制的构建过程设置输出软件包摘要(SLSA溯源中的主题),而可信的控制平面未验证是否实际生成了这样的软件包。
缓解措施:无;这不是一个问题。任何声称生成给定软件包的构建都可以通过将其从输入复制到输出来实际生成它。
示例:一个合法的MyPackage软件包具有摘要abcdef,并从源代码库good/my-package构建。一个恶意构建从源代码库evil/my-package声称它构建了软件包abcdef,但实际上并没有。解决方案:验证器拒绝,因为源位置不匹配;伪造的摘要是无关紧要的。
2.3.1.3. 入侵项目所有者(构建L2+)
威胁:对手获得软件包构建项目的所有者权限。
缓解措施:构建项目所有者不能影响构建过程或溯源生成。
示例:MyPackage在Awesome Builder上构建,项目名为“mypackage”。对手是“mypackage”项目的管理员。Awesome Builder允许管理员通过SSH调试构建机器。对手利用此功能来更改正在进行的构建。
2.3.1.4. 入侵其他构建(构建L3)
威胁:执行恶意构建,以更改并行或后续环境中良性构建的行为。
缓解措施:构建之间相互隔离,彼此之间无法相互影响或保留更改。
示例1:构建平台在同一台机器上以相同的Linux用户运行MyPackage项目的所有构建。对手启动一个恶意构建,监听另一个构建并替换源文件,然后启动一个良性构建。良性构建使用恶意构建的源文件,但其溯源声称使用良性源文件。解决方案:构建平台更改架构,以在单独的虚拟机或类似环境中隔离每个构建。
示例2:构建平台在后续构建中使用同一台机器。对手首先运行一个构建,将make二进制文件替换为恶意版本,然后随后运行一个其他正常的构建。解决方案:构建者更改架构,以使用干净的机器镜像开始每个构建。
2.3.1.5. 窃取加密密钥(构建L3)
威胁:使用或窃取仅应对构建平台可用的溯源签名密钥或其他加密密钥。
缓解措施:构建与可信的构建平台控制平面相互隔离,只有控制平面可以访问加密密钥。
示例:溯源在构建工作机上签名,而对手控制该机器。对手使用恶意进程生成虚假溯源,并使用溯源签名密钥对其进行签名。解决方案:构建者在可信的控制平面上生成并签名溯源;工作机无法访问密钥。
2.3.1.6. 污染构建缓存(Build L3)
威胁:向构建缓存中添加一个恶意构件,然后被良性构建过程所使用。
缓解措施:构建缓存必须在构建之间进行隔离,以防止此类缓存污染攻击。
示例:构建平台在构建之间使用一个由源文件哈希键控的构建缓存。攻击者运行一个创建了一个“有毒”缓存条目的恶意构建,其中包含一个伪造的键,意味着该值实际上并不是从该源文件生成的。随后的构建会使用到这个有毒的缓存条目。
2.3.1.7. 入侵构建平台管理员(验证)
威胁:攻击者获得构建平台的管理员权限。
缓解措施:构建平台必须采取控制措施来防止和检测管理员的滥用行为(例如,两人审批,审计日志记录)。
示例:MyPackage在Awesome Builder上构建。Awesome Builder允许值班工程师通过SSH连接到构建机器以调试生产问题。攻击者利用此访问权限修改正在进行的构建。解决方案:消费者不接受来自构建平台的来源,除非他们相信已经采取了足够的控制措施来防止滥用管理员权限。
2.3.2. 上传修改后的软件包
攻击者上传了一个不是通过正确构建过程构建的软件包。
2.3.2.1. 使用不受信任的CI/CD进行构建
威胁:使用非官方的CI/CD流水线进行构建,不按正确的方式构建。
缓解措施:验证器要求提供证明构建者与预期值匹配的来源。
示例:MyPackage预期在受信任的Build L3上由Google Cloud Build构建。攻击者在只受信任到Build L2的SomeOtherBuildPlatform上构建,然后利用SomeOtherBuildPlatform注入恶意行为。解决方案:验证器拒绝,因为构建者与预期不符。
2.3.2.2. 上传没有来源的软件包(Build L1)
威胁:上传一个没有来源的软件包。
缓解措施:验证器在接受软件包之前要求提供来源。
示例:攻击者向软件包仓库上传了一个没有来源的恶意版本的MyPackage。解决方案:验证器拒绝,因为缺少来源。
2.3.2.3. 在CI/CD之后篡改构件(Build L1)
威胁:获取软件包的良性版本,以某种方式进行修改,然后使用原始来源重新上传。
缓解措施:验证器检查来源的主题是否与软件包的哈希值匹配。
示例:攻击者进行正确的构建,修改了构件,然后将修改后的软件包版本与来源一起上传到仓库。解决方案:验证器拒绝,因为构件的哈希值与来源中的主题不匹配。
2.3.2.4. 篡改来源(Build L2)
威胁:进行不符合预期的构建,然后修改来源以使预期检查通过。
缓解措施:验证器只接受带有有效的加密签名或等效证明的来源,证明该来源来自可接受的构建者。
示例:MyPackage预期由good/my-package仓库中的GitHub Actions构建。攻击者使用evil/my-package仓库中的GitHub Actions构建,并修改了来源,使其看起来像是来自good/my-package。解决方案:验证器拒绝,因为加密签名不再有效。
2.3.3. 入侵软件包仓库
攻击者通过管理接口或者通过对基础设施的入侵修改软件包在软件包注册表上的内容。
2.3.3.1. 取消列出软件包
威胁:软件包注册表停止提供软件包。
缓解措施:N/A - 此威胁超出了SLSA v1.0的范围。
2.3.3.2. 取消列出来源
威胁:软件包注册表停止提供来源。
缓解措施:N/A - 此威胁超出了SLSA v1.0的范围。
2.3.4. 使用被入侵的软件包
对手在软件包离开软件包注册表后修改软件包,或者欺骗用户使用意外的软件包。
2.3.4.1. Typosquatting(拼写错误域名攻击)
威胁:注册一个与热门软件包相似的软件包名称,并让用户使用您的恶意软件包而不是良性软件包。
缓解措施:大部分超出了SLSA的范围。尽管如此,要求提供源代码可作为一种轻微的威慑手段,可以帮助调查或临时分析,并可以与基于源代码的拼写错误域名解决方案相辅相成。
回顾:SolarWinds攻击涉及以上???
参考链接:
[1] https://github.com/slsa-framework/slsa