上一秒还在想「谁没事盯我仓库」,下一秒 git ls-remote 一拉,多出来一个 ci-sync-a3f9k2 分支。它不是谁在改代码,是有人拿了一个偷来的 GitHub token,在你仓库里做了一件平台本来就允许的事——把 secret 打印到日志里。
先把话说前头:这不是哪个软件出了漏洞。攻击者用的是偷来的 token,所以他能进哪些仓库、能干多少事,全看那个 token 当初被授了多大权限。
动作很固定,就三步:
- 用 token 在每个有权限的仓库建一个分支,名字是
ci-sync-加 6 位随机字符; - 提交一个
.github/workflows/sync-check.yml,commit message 固定写ci: sync config,没签名,作者显示成 token 的主人; - 这个 workflow 只干一件事——把
toJSON(secrets)打出来。
关键就在第 3 步。GitHub 给日志打码,只对原样出现的 secret 生效。工具把 secret 先做一次 base32 编码再打印,编码后的串跟原值对不上,打码逻辑就绕过去了,明文落进日志。
紧接着,工具通过 GitHub 自己的 API 把这次 run 的日志拉走,几秒内把 run 删掉。等你再打开 Actions 页面,什么痕迹都没有。
这也是它躲得出网告警的原因:整条外泄走的是 GitHub 自己的 API,没有攻击者域名、没有异常外连,在监控眼里就是「你们家 CI 在拉自己的日志」。
哪些仓库挡得住、哪些挡不住,这点值得记一下:公开仓库有 7/28 上线的「可疑 workflow 需人工批准」盯着,会拦;私有仓库和 GitHub Enterprise Server 不适用这条——已经观察到私有仓库里的 run 正常跑完、然后被删。有 environment 的仓库还要更糟一层:攻击者用 job matrix 把 environment 级的 secret 也打出来,而 environment 里放的通常就是生产凭证。
顺带一句,像 permissions: {} 这种收紧,限制的是 GITHUB_TOKEN,管不到 secrets 这个上下文,别指望它兜底。
企业环境里的后续通常是:几分钟内轮换多个用户和自动化账号的 token,先把私有仓库 clone 走;几个小时后,同一个组织在云上的凭证开始被拿去枚举 AWS Secrets Manager。
影响面:850+ 个账号、13,500+ 个植入分支,从个人项目到企业私有仓库。凭证来源是 infostealer 日志,以及此前供应链事件(比如 3 月 Trivy)里漏出去的 token。
修复版本:不适用,它不是软件漏洞。要做的处置是:轮换该仓库能见到的全部 secret、revoke 掉 token。如果有 self-hosted runner 跑过这个 workflow,那台机器直接当失陷处理。
一条自查:git ls-remote --heads origin 'refs/heads/ci-sync-*',有输出就是被种过。
这跟之前那次 GitLab 自己的 CI 洞 是一个道理:大家平时防的是出网、防的是恶意依赖,很少有人防「平台自带的功能被拿来当外泄通道」。也像更早 堡垒机那次——不是洞有多高明,是拿到的凭证能用多久、能走多远,没人算过账。
原始来源:Wiz Research《Gheist: attempted scaled abuse of stolen GitHub tokens stumbles》:https://www.wiz.io/blog/gheist-attempted-scaled-abuse-of-stolen-github-tokens-stumbles
评论