跳到内容

CI/CD 安全备忘录

简介

CI/CD 管道和流程有助于高效、可重复的软件构建和部署;因此,它们在现代 SDLC 中扮演着重要角色。然而,鉴于其重要性和普及性,CI/CD 管道也成为恶意攻击者的诱人目标,其安全性不容忽视。本备忘录旨在为开发人员提供实用指南,以降低与这些关键组件相关的风险。本备忘录将重点关注管道本身的安全性。它将首先提供一些简要的背景信息,然后介绍具体的 CI/CD 安全最佳实践。

定义与背景

CI/CD 指的是一套主要用于构建和交付软件的自动化流程;它通常被描绘成由一系列连续、离散的步骤组成的管道。该管道通常在开发中的代码被推送到存储库时开始,如果所有步骤都成功完成,则以软件解决方案的构建、测试和部署到生产环境而结束。CI/CD 可以分解为两个不同的部分:持续集成 (CI) 和持续交付和/或持续部署 (CD)。CI 侧重于构建和测试自动化;持续交付侧重于将此构建的代码提升到预演或更高级别的环境,并通常执行额外的自动化测试。在 CI/CD 的定义中,持续交付和持续部署可能并不总是区分开来;然而,根据 NIST 的说法,持续交付需要手动将代码推送到生产环境,而持续部署甚至将此步骤自动化。

CI/CD 管道中的确切步骤可能因组织和项目而异;然而,自动化以及它带来的可重复性和敏捷性,应是任何 CI/CD 实施的核心焦点。

了解 CI/CD 风险

虽然 CI/CD 带来了诸多好处,但它也增加了组织的攻击面。CI/CD 需要人员、流程和技术,而所有这些都可能成为攻击途径;代码存储库、自动化服务器(如 Jenkins)、部署程序以及负责运行 CI/CD 管道的节点,都只是可能被恶意实体利用的 CI/CD 组件的几个例子。此外,由于 CI/CD 步骤经常使用高权限身份执行,因此针对 CI/CD 的成功攻击通常具有高破坏潜力。如果一个组织选择利用 CI/CD 的诸多好处,它也必须确保投入所需的资源来正确保护它;CodecovSolarWinds 漏洞只是 CI/CD 泄露潜在影响的两个发人深省的例子。

攻击者利用 CI/CD 环境的具体方法多种多样;然而,某些风险比其他风险更为突出。虽然不应局限于对它们的了解,但理解 CI/CD 环境中最突出的风险可以帮助组织更有效地分配安全资源。OWASP 十大 CI/CD 安全风险 是实现此目的的宝贵资源;该项目将以下内容列为十大 CI/CD 风险:

  • CICD-SEC-1:不充分的流量控制机制
  • CICD-SEC-2:不充分的身份和访问管理
  • CICD-SEC-3:依赖链滥用
  • CICD-SEC-4:中毒管道执行 (PPE)
  • CICD-SEC-5:不充分的 PBAC(基于管道的访问控制)
  • CICD-SEC-6:不充分的凭证卫生
  • CICD-SEC-7:不安全的系统配置
  • CICD-SEC-8:不受管制的第三方服务使用
  • CICD-SEC-9:不当的工件完整性验证
  • CICD-SEC-10:不充分的日志记录和可见性

本备忘录的其余部分将重点提供关于缓解这十大风险以及其他 CI/CD 风险的指导。

安全配置

必须投入时间和精力来正确保护支持 CI/CD 流程的组件,例如 SCM 系统和自动化服务器(Jenkins、TeamCity 等)。无论使用何种具体工具,都绝不能盲目依赖供应商的默认设置。同时,在未充分了解其影响的情况下,不得随意调整设置,也不得以不受控制、完全临时的方式执行任何所需的配置更新。必须建立变更管理和适当的治理。此外,教育是关键;在利用工具执行关键的、安全敏感的操作(如代码部署)之前,务必花时间了解底层技术。安全配置不会自动发生;它需要教育和规划。

此外,还必须采取措施确保用于运行或支持上述 CI/CD 组件的操作系统、容器镜像、Web 服务器或其他基础设施的安全。这些系统必须得到适当的补丁更新,并且应维护这些资产的清单,包括软件版本。这些技术应根据适用的标准(如 CIS 基准STIGs)进行加固。

除了这些一般原则外,下文还将探讨一些与 CI/CD 配置相关的具体指导方针。

安全 SCM 配置

CI/CD 环境允许代码被推送到存储库,然后几乎无需手动干预即可部署到生产环境。然而,如果它允许不受信任的、可能恶意的代码直接部署到生产系统,这种优势可能会迅速成为攻击向量。正确配置 SCM 系统有助于缓解此风险。最佳实践包括:

  • 避免在 GitlabGithub 或 Bitbucket 等平台中使用自动合并规则。
  • 要求拉取请求在合并前进行审查,并确保此审查步骤无法绕过。
  • 利用 受保护的分支
  • 要求提交经过签名。
  • 仔细权衡允许临时贡献者带来的风险与收益。在可能的情况下,限制外部贡献的数量和权限。
  • 在可用时启用 MFA。
  • 避免为有权访问您的 SCM 资产的用户和角色分配默认权限。仔细管理您的权限。
  • 限制私有或内部存储库的分叉能力。
  • 限制将存储库可见性更改为公开的选项。您可以在此 文档 中找到各种附加策略。

为了帮助应对 SCM 配置挑战,有可用的工具,例如由 Legit security 开发的开源工具 Legitify。Legitify 扫描 SCM 资产并识别错误配置和安全问题,包括上述所有最佳实践的策略(适用于 GitHub 和 GitLab)。

管道与执行环境

除了 SCM 系统外,负责运行管道的自动化服务器也必须安全配置。这些技术的例子包括 Travis、TeamCity、Jenkins 和 CircleCI。虽然具体的加固过程会根据所使用的特定平台而异,但一些一般最佳实践包括:

  • 在适当隔离的节点中执行构建(参见 Jenkins 示例 此处
  • 确保 SCM 与 CI/CD 平台之间的通信使用广泛接受的协议(如 TLS 1.2 或更高版本)进行保护。
  • 如果可能,按 IP 限制对 CI/CD 环境的访问。
  • 如果可行,将 CI 配置文件存储在托管正在构建的代码的存储库之外。如果文件与代码一同存储,则必须在批准任何合并请求之前审查该文件。
  • 启用适当级别的日志记录(详见下文 可见性与监控
  • 将适合语言的 SAST、DAST、IaC 漏洞扫描和相关工具集成到管道中。
  • 在触发生产部署之前,要求手动批准和审查。
  • 如果管道步骤在 Docker 镜像中执行,请避免使用 --privileged 标志 参考
  • 确保管道配置代码受版本控制 (参考)
  • 在可能的情况下强制执行 MFA。

IAM

身份和访问管理 (IAM) 是管理数字身份并控制其对数字资源访问的过程。身份的示例包括系统帐户、角色、组或个人用户帐户。IAM 的应用范围远超 CI/CD,但身份及其底层凭证的管理不当是影响 CI/CD 环境最突出的风险之一。以下小节将重点介绍一些与 IAM 相关的安全最佳实践,这些实践与 CI/CD 环境尤为相关。

密钥管理

密钥(例如 API 密钥或密码)通常是 CI/CD 管道成功执行所必需的。CI/CD 环境中的密钥通常数量众多,其中至少有一些提供了对敏感系统或操作的实质性访问。这种组合带来了一个挑战:如何在安全地管理密钥的同时,允许自动化 CI/CD 流程根据需要访问它们?遵循一些简单的指导方针可以帮助显著缓解(尽管肯定不能完全消除)风险。

首先,应采取措施降低密钥以可用格式被盗的可能性。密钥绝不应硬编码在代码存储库或 CI/CD 配置文件中。使用 git-leaksgit-secrets 等工具来检测此类密钥。努力从一开始就阻止密钥被提交,并进行持续监控以检测任何偏差。密钥还必须从其他工件(如 Docker 镜像和编译后的二进制文件)中移除。密钥必须始终使用行业公认的标准进行加密。当密钥存储在文件系统、保管库或类似存储中时,必须对其进行加密;然而,还必须确保这些密钥不会因在 CI/CD 管道中使用而以明文形式泄露或持久化。例如,密钥不得打印到控制台、记录日志或存储在系统的命令历史文件(如 ~/.bash-history)中。为此目的,可以使用第三方解决方案,例如 HashiCorp VaultAWS Secrets ManagerAKeylessCyberArk

其次,必须采取措施,在密钥以攻击者可用的格式被盗时,降低其影响。使用临时凭证或 OTP 是一种降低影响的方法。此外,还可以施加基于 IP 或其他限制,如果未满足这些进一步要求,即使是有效凭证也无法访问资源。下文的最小权限身份生命周期管理部分提供了关于缓解与密钥盗窃相关风险的技术的进一步指导。

有关安全管理密钥的更多指导,请参考密钥管理备忘录

最小权限原则

最小权限,NIST 的定义为:

“一种安全架构设计原则,即每个实体仅被授予执行其功能所需的最小系统资源和授权。”

在 CI/CD 环境中,此原则应至少应用于三个主要领域:管道步骤中用于访问外部资源的密钥、一个管道或步骤对 CI/CD 平台中配置的其他资源的访问权限(Palo Alto Networks,无日期),以及执行管道的操作系统用户的权限。

无论具体应用如何,一般指导原则保持不变:访问必须合理,而不是假设。应采用“默认拒绝”的心态。管道中使用的任何身份必须只被分配完成其工作所需的最小权限。例如,如果管道必须访问 AWS 服务才能完成其任务,则该管道中使用的 AWS 凭证必须只能对执行其任务所需的特定服务和资源执行特定操作。类似地,跨管道的凭证共享应保持在最低限度;特别是,不同敏感度或价值级别的管道之间不应发生此类共享。如果管道 A 不需要访问管道 B 所需的相同密钥,理想情况下它们不应共享。最后,负责运行管道的操作系统帐户不应具有 root 或可比的特权;这将有助于在发生泄露时减轻影响。

身份生命周期管理

尽管适当的密钥管理和最小权限原则的应用对于安全的 IAM 至关重要,但它们并不充分。从创建到注销的身份生命周期必须仔细管理,以降低 CI/CD 和其他环境的风险。

在身份管理(如 ILM 手册 中定义)的初始或“加入者”阶段,考虑因素包括使用集中式 IdP 而不是允许本地帐户、禁止共享帐户、禁止身份的自助配置,以及只允许使用由负责 CI/CD 环境的组织控制的域的电子邮件帐户(OWASP,无日期)。一旦配置完成,身份必须被跟踪、维护,并在必要时进行注销。在复杂、分布式 CI/CD 环境中,特别需要关注的是确保维护一份准确、全面且最新的身份清单。此清单的格式可能因组织需求而异,但除了身份本身之外,建议的字段包括身份所有者或责任方、身份提供者、上次使用时间、上次更新时间、授予的权限以及身份实际使用的权限。这样的清单将有助于人们轻松识别可能拥有过多权限或可能被注销的身份。适当的身份维护绝不能忽视;“被遗忘”的身份可能成为攻击者用来入侵 CI/CD 系统的载体。

管理第三方代码

部分由于 SolarWinds 等备受关注的漏洞,软件供应链安全的概念近年来受到越来越多的关注。这个问题在 CI/CD 环境中尤为紧迫,因为此类环境以多种方式与第三方代码交互。以下将讨论两个此类交互领域:管道中运行的项目所使用的依赖项以及与 CI/CD 系统本身的第三方集成和插件。

依赖项管理

使用具有已知漏洞的第三方软件包是软件工程中一个众所周知的问题,并且已经开发了许多工具来解决这个问题。在 CI/CD 环境中,自动化使用 SCA 和可比较的工具实际上可以帮助提高此领域的安全性。然而,CI/CD 环境本身易受另一种但相关的风险影响:依赖链滥用。

依赖链滥用涉及利用系统依赖链和依赖解析过程中的缺陷;成功的攻击可能导致执行来自攻击者控制的恶意软件包中的代码。依赖链本身指的是软件解决方案正常运行所需的一组软件包,包括内部、直接第三方和传递依赖项。攻击者可以通过诸如依赖混淆拼写劫持(typosquatting)或接管有效软件包维护者帐户等方法来利用此依赖链。依赖链滥用攻击可能相当复杂,因此全面的防御也相应复杂;然而,基本的缓解措施相当直接。

缓解技术始于 SDLC 的早期阶段,远在 CI/CD 管道开始执行之前。项目的包管理技术(如 npm)应配置为确保依赖项引用不可变(CISA 等人,2022)。应执行版本锁定(version pinning),所选的锁定版本必须是已知有效且安全的版本,并且系统下载的任何包的完整性应通过将其哈希或校验和与锁定包的已知良好哈希进行比较来验证。实现此目的的具体程序将根据项目的底层技术而异,但总的来说,版本锁定和哈希验证都可以通过平台的“锁定”文件或类似文件(即 package-lock.jsonPipfile.lock)执行。在可能的情况下,首选使用私有存储库,并配置包管理器仅使用单个私有源(Microsoft,2021)。对于私有包,利用 scoped NPM 包NuGet 包的 ID 前缀或类似功能,以降低依赖混淆的风险。最后,无论使用何种平台,请确保负责控制这些设置的文件(例如 Node 环境中的 .npmrc)已提交到源代码管理并可在 CI/CD 环境中访问。

插件与集成管理

大多数 CI/CD 平台都可以通过插件或其他第三方集成进行扩展。虽然这些扩展可以带来许多好处,包括可能提高系统的安全能力,但它们也增加了攻击面。这并不是说插件必须被禁用;相反,必须简单地考虑风险并将其降低到可接受的水平。

插件的安装或与第三方服务的集成应被视为任何软件的采购。这些工具通常易于安装和设置,但这并不意味着它们的安装和使用可以不受管制。必须强制执行最小权限原则,以确保只有少数用户拥有扩展 CI/CD 平台所需的权限。此外,此类扩展在安装前必须经过审查。需要考虑的问题与采购任何软件前应提出的问题类似:

  • 供应商是否是公认和受人尊敬的开发商或公司?
  • 供应商在应用程序安全方面是强还是弱?
  • 特定插件或集成端点有多受欢迎?
  • 插件或集成是否仍在积极维护?
  • 扩展是否需要可能降低安全性的配置更改(例如暴露额外端口)?
  • 组织是否拥有适当配置和维护该产品所需的经验和资源?

插件或其他集成获得批准后,必须将其纳入组织的配置管理流程。软件必须保持最新,特别是任何可用的安全补丁。还必须持续审查扩展的价值;如果不再需要,应将其移除。

完整性保证

CI/CD 攻击通常需要攻击者插入到管道的正常流程中,并修改一个或多个步骤的输入和/或输出。因此,完整性验证是降低 CI/CD 环境风险的重要方法。

与许多其他防御行动一样,完整性相关控制的实施始于 SDLC 的早期阶段。如前所述,SCM 应要求提交在代码合并前进行签名。此外,如 依赖项管理 中所讨论,包管理平台应配置为使用哈希或类似方法来验证包的完整性。还应采用代码签名;为此目的可以使用 SigstoreSignserver 等技术。然而,重要的是要注意,代码签名及相关技术并非安全性的绝对保证;代码签名过程本身也可能被利用。请参阅 NIST 关于代码签名的安全注意事项,以获取有关保护代码签名过程的更多指导。最后,集成 in-toto.to 框架或类似框架可以进一步帮助提高 CI/CD 环境中的完整性。

可见性与监控

CI/CD 环境可能很复杂,对开发人员来说常常像一个黑箱。然而,对这些系统的可见性对于检测潜在攻击、更好地了解风险状况以及检测和修复漏洞至关重要。尽管日志记录和日志分析的价值常常被低估,但它们对于提供 CI/CD 系统的可见性至关重要。

提高 CI/CD 可见性的第一步是确保 CI/CD 环境中的日志配置符合组织的日志管理策略。除了遵守内部策略外,还应将系统配置为以易于解析的格式(如 JSON 或 syslog)记录数据。仔细考虑需要记录哪些内容以及记录的详细程度。尽管适当的日志记录应允许管道的端到端可见性,但更多的日志记录并非天生就更好。不仅要考虑与日志相关的存储成本,还要注意避免记录任何敏感数据。例如,大多数与身份验证相关的事件可能都应记录。然而,绝不应记录明文密码、身份验证令牌、API 密钥或类似的秘密。

一旦定义了适当的日志记录策略并完成了必要的配置,就可以开始利用这些日志来降低风险。将聚合日志发送到集中式日志管理系统,或者最好是 SIEM,是实现日志价值的第一步。如果使用 SIEM,应仔细配置警报并定期完善,以便及时提供异常和潜在攻击的警报。确切的配置将根据 CI/CD 环境、SIEM 平台和其他因素而有很大差异。有关 ELK Stack(一个流行的 SIEM 平台)背景下的 CI/CD 可观测性概述,请参阅这篇文章,或参考这篇文章以获取可轻松适应各种 CI/CD 环境的替代方法。重要的是要记住,SIEM 警报在检测 CI/CD 攻击时永远不会 100% 准确。假阳性(误报)和假阴性(漏报)都会发生。不应盲目依赖此类平台,但它们确实为 CI/CD 环境提供了重要的可见性,并在经过深思熟虑的配置后,可以作为重要的警报系统。

参考资料

一般参考

CI/CD 平台

IaC 扫描

完整性验证与签名

密钥管理工具