GH Actions - Cache Poisoning

支持 HackTricks

有关更多详细信息,请查看原始帖子 https://scribesecurity.com/blog/github-cache-poisoning/

Cache Poisoning

Git 操作 action/cache 在持续集成 (CI) 过程中引入了缓存机制,涵盖两个关键阶段:

  1. 运行操作:此阶段涉及在 CI 运行期间搜索和检索缓存数据。搜索使用唯一的缓存键,产生两个结果:

  • 缓存命中:在缓存中找到请求的数据,并因此被检索以供立即使用。

  • 缓存未命中:在缓存中未找到匹配的数据,促使重新下载所需的文件和目录,类似于首次请求。

  1. 工作流后操作:此阶段专注于在 CI 工作流后缓存数据。具体而言,如果在运行操作期间发生缓存未命中,则使用提供的键缓存指定目录的当前状态。此过程是自动化的,不需要显式调用。

安全措施:缓存隔离和访问限制

为了维护安全性并确保缓存隔离,实施了访问限制,创建了不同分支之间的逻辑分离。例如,为分支 Feature-A(以主分支为基础)创建的缓存将无法被分支 Feature-B(同样以主分支为基础)的拉取请求访问。

缓存操作遵循特定的搜索顺序:

  • 首先在与工作流运行相同的分支中寻找缓存命中。

  • 如果不成功,则扩展搜索到父分支和其他上游分支。

重要的是,缓存访问是基于分支的,扩展到特定分支的所有工作流和运行。此外,GitHub 对缓存条目实施只读策略,一旦创建,禁止任何修改。

现实世界的影响:从低权限工作流攻击到高权限工作流攻击

一个示例 CI 场景演示了攻击者如何利用缓存中毒将权限从低权限工作流提升到高权限工作流:

  • 单元测试 工作流,负责运行单元测试和代码覆盖工具,假设使用了一个被破坏或脆弱的工具。此工作流利用 action/cache Git 操作,使缓存对任何工作流可访问。

  • 发布 工作流,负责构建和发布应用程序工件,通过缓存 Golang 依赖项来优化其操作。

在此场景中,单元测试工作流通过替换一个合法的 Golang 日志库引入了一个恶意缓存条目(`go

Last updated