Argon(现在是 Aqua Security 的一部分)曾经联系 CIS(Center for Internete Security),建议为软件供应链安全开发一种 CIS 基线。多年以来,CIS 开发并发布了很多安全配置指南,但是软件供应链安全方面还是一个空白。现代软件开发过程中会涉及大量的平台和技术,软件供应链安全的工作范围应该有多大?如何保证基线能够在多种平台中保持一致?
很明显,要直接定义特定的基线是不现实的,更实际的做法是定义一个通用的指南,然后以此为基础来进一步定义更精准的内容。因此 CIS 软件供应链安全指南诞生了。这篇指南的目的在于引出全球社区的反馈,从而帮助制定未来的更准确、更针对特定平台的指南。
本指南面向下图所示的软件供应链过程,涵盖了从代码到交付的生命周期。
本指南目前包含了一百多条建议,按照以下维度进行组织:
本指南和 CIS 基准的愿景,是支持关键的新兴标准,如软件产品的供应链级别(SLSA)和更新框架(TUF),为基准支持的平台上的配置设置和审计工作奠定基础。
通过制定 CIS 软件供应链指南,CIS 和 Aqua 希望建设一个活跃的社区,来支持开发未来的针对平台的软件供应链基线。呼吁开发这些平台或与这些平台合作的专家(Subject Matter Experts)以 CIS 的协作和共识方式帮助创建这一指南。
迄今为止,来自 Aqua Security、CIS、Microsoft、PayPal、Red Hat、CyberArk、Axonius 等组织的 SME 们已经对本指南进行了评审。CIS 和 Aqua Security 希望开放目前工作成果的方式,吸引有更多的 SME 为这个项目做出贡献,使所有人受益。
要贡献给 CIS 基线项目,请联系 CIS 基线开发团队:benchmarkinfo@cisecurity.org。
本指南适用于计划通过 DevOps 管道的自动化手段构建和部署软件更新的开发、部署、评估或保护解决方案的 DevOps 和应用安全管理员、安全专家、审计师、Help Desk 和平台部署人员。
1.1 代码变更
1.1.1 使用版本控制平台来跟踪代码变更
1.1.2 确保能够从变更代码回溯到对应的任务
1.1.3 保证由两个强认证用户对代码变更进行评审和放行
1.1.4 如果代码变更的内容发生了更新,那么之前批准的变更申请应该作废
1.1.5 对于撤销变更评审结果的权限应该严加管控
1.1.6 为敏感代码或配置设置明确的所有者
1.1.7 代码属主的代码发生变更时,必须由属主进行审批
1.1.8 周期性地对不活跃分支进行评审和删除
1.1.9 合并新代码之前,必须通过所有检查
1.1.10 进行代码合并之前,确保 Git 分支是最新的
1.1.11 进行代码合并之前,确保所有开放注解都已经解决
1.1.12 合并之前需要对提交内容进行签署
1.1.13 留存 Linear History(仅能合并 Squash 或 Rebase 内容)
1.1.14 制定分支的管理规则
1.1.15 确保由特定的个人或者团队来完成代码合并过程
1.1.16 拒绝向保护分支强行推送代码
1.1.17 只有推送权限的用户不能删除分支
1.1.18 所有的合并操作都需要进行风险扫描
1.1.19 分支保护规则的变更需要进行审计
1.2 仓库管理
1.2.1 所有公开仓库都应该包含 文件
1.2.2 只有特定人/角色能够创建仓库
1.2.3 只有特定人/角色能够删除仓库
1.2.4 只有特定人/角色能够删除 Issue
1.2.5 确保跟踪所有代码的副本(分叉)
1.2.6 确保跟踪项目代码的可见性(可访问性)变化
1.2.7 周期性的评审不活跃代码仓并进行归档
1.3 访问代码库
这一节包含了在管理应用代码访问过程中的推荐安全措施。这其中包含了对内部和外部访问、账号管理、授权、认证方式等方面的内容。对于访问的安全限制是阻止攻击的重要手段,因此这一节内容是软件安全的重要组成部分。
本节对管理员账户和普通账户分而治之。因为管理员的权限过大,因此管理员账户只应用于管理工作,而非日常任务。
1.3.1 周期性评审不活跃用户并进行删除
1.3.2 确保只有特定用户才能创建团队
1.3.3 严格限制管理员数量
1.3.4 组织外贡献者需要进行多因素认证
1.3.5 组织成员需要进行多因素认证
1.3.6 组织中的现有用户可以邀请新用户加入,新成员只能使用公司认证的邮箱接收邀请
1.3.7 每个代码仓都需要有两个管理员
1.3.8 为代码仓设置严格的基础(缺省)权限
1.3.9 明确标识认证的组织,防止被仿冒
1.3.10 确保仅向认证的域发送源码管理系统的通知邮件
1.3.11 组织应提供 SSH 认证方法
1.3.12 根据 IP 地址限制 Git 访问
1.3.13 跟踪反常的代码访问行为
1.4.1 安装自动化插件/工具需要由管理员批准
1.4.2 周期性地检查过期插件/工具,并删除
1.4.3 应限制自动化工具/插件的最小权限
1.5 代码风险
本节包含代码安全扫描方面的建议。例如硬编码的敏感信息、常见的导致易受攻击的配置错误或者严格的授权等。因为应用代码有很多组件,因此需要逐一检查。
1.5.1 确保使用扫描器鉴别并阻止代码中出现敏感数据
1.5.2 CI 管线中应该有扫描器
1.5.3 IaC 指令必须通过扫描器的检查
1.5.4 用扫描器扫描漏洞
1.5.5 确保使用扫描器扫描引用的开源包中的漏洞
1.5.6 确保使用扫描器扫描引用的开源包的授权
本节针对组织开发的构建管线,提出安全建议。
构建管线是一组基础设施,会读取原始的代码问价,运行一组任务,最终输出制品。制品是软件最近版本的最终输出物,这些输出物会被打包以便于后续的存储、使用和部署。
2.1 构建环境
本节针对构建管线的环境提出安全建议。构建环境包含所有制品构建过程所需的基础设施——编排器、管线执行、构建器所在的环境等。绝大多数构建环境的安全建议是针对自建构建平台的——例如自建的 Circle CI。
2.1.1 每个管线都有单一职责,确保最小化权限
2.1.2 每个管线的基础设施和配置都是不可变的
2.1.3 需要保存构建环境的日志
2.1.4 能够自动创建构建环境
2.1.5 对构建环境进行访问控制
2.1.6 仅有认证用户能够访问构建环境
2.2 构建 Worker/Runner
2.2.1 每种构建 Worker 只有单一用途
2.2.2 构建 Worker 的运行环境和命令应该是从外部推送给 Worker,而不是由 Worker 主动拉取
2.2.3 不同 Worker 的职责应该分离
2.2.4 尽可能缩减 Worker 的网络连接能力
2.2.5 Worker 需要进行加固保障运行时安全
2.2.6 要对 Worker 进行漏洞扫描
2.2.7 Worker 的部署配置应该保存在版本控制系统里
2.2.8 监控 Worker 的资源消耗
2.3 管线指令
管线中使用指令来获取源代码的原始文件,并进行一系列处理最终输出制品。多数时候,这些指令是由第三方开发者编写的,受攻击的几率可能较高,因此需要谨慎对待。
2.3.1 确保所有构建步骤都以代码定义
将管道指令作为代码存储在版本控制系统中,提高了构建步骤的自动化程度,并减少人为错误导致的安全漏洞。此外,这种做法也具备了恢复管道配置版本的能力,在发生恶意事件时,更容易准确的定位受影响的变化。
2.3.2 清晰声明构建步骤的输入和输出内容
2.3.3 确保输出内容写入到独立的、安全的存储仓
2.3.4 管线文件需要进行跟踪和评审
2.3.5 确保构建过程的触发有严格权限控制
2.3.6 使用自动扫描的方式保障管线配置正确性
2.3.7 使用自动扫描的方式避免管线漏洞
2.3.8 使用自动扫描的方式避免管线中出现敏感数据
2.4 管线完整性
确保管线、管线的依赖项以及相关制品都是真实的。管道的完整性能保障管道运行过程中的每一个变化和进程都是有保障的。一个办法就是将每个依赖关系锁定在某个安全版本上。
2.4.1 为所有版本的所有制品进行签名
2.4.2 锁定所有构建过程中的外部依赖
2.4.3 在引入依赖之前要进行验证
2.4.4 构建管线的制品生成应该具有复现能力
2.4.5 管线步骤应该能生成 SBOM(软件物料单)
2.4.6 管线应对生成的 SBOM 进行签名
3.1 三方包
3.1.1 要对第三方制品和开源库进行校验
3.1.2 所有第三方供应商都应该提供 SBOM
3.1.3 构建过程生成的(历史)元数据应该被签名和校验
3.1.4 确保开源组件的依赖关系也得到监控
3.1.5 定义并优先使用受信任的包管理器及其包仓库
3.1.6 为代码的 SBOM 进行签名(太啰嗦了)
3.1.7 依赖应该锁定到一个特定的、验证过的版本
3.1.8 使用的所有包都发布于至少 60 天以前
3.2 包校验
3.2.1 要在组织范围内实施依赖使用策略
3.2.2 要能够自动扫描已知漏洞
3.2.3 要能够自动扫描许可问题
3.2.4 能够自动扫描包的属主变化
制品是软件的打包成果,保存在包仓库中或者制品库中,从产生到拷贝、更新以及部署的整个过程都需要关注安全问题。
4.1 校验
制品被推送到仓库之后,可能发生各种攻击:例如使用同名恶意制品进行覆盖、盗取制品文件等。