技术

Megalodon在6小时内把GitHub Actions变成了5,561个仓库的后门

Susan Hill

一场自动化的活动在5月某个周一上午6小时内向5,561个GitHub仓库推送了5,718次提交。这些提交看上去像普通的CI维护工作(”ci: add build optimization step”、”build: improve ci performance”、”chore: optimize pipeline runtime”),来自build-bot、auto-ci、pipeline-bot这类毫不起眼的作者。等到5月18日上午结束,这些仓库里都已多出一个工作流文件,里面坐着一段base64编码的bash载荷。

这场活动名叫Megalodon。SafeDep的研究团队在5月21日公开披露:他们先拆开提交,再沿着工件痕迹追到一台位于216.126.225.129:8443的指挥控制服务器。值得注意的并不是GitHub被攻击。值得注意的是攻击者根本不必入侵GitHub。他们使用了GitHub Actions——那套专门为保证代码完整性而设计的CI/CD系统——当作后门的投递载具。

两种工作流:一个全量,一个潜伏

Megalodon以两种模式运行。全量变种新增了一份名为SysDiag的工作流文件,在每次push和每次pull request时触发,把经过它的一切尽数收走。定向变种Optimize-Build则更有耐心:它把已有的工作流替换为workflow_dispatch触发器,让它在有人手动调用之前一直沉睡。一个潜伏在项目CI目录里的后门,比一个新名字SysDiag的工作流难发现得多——因为大多数维护者不会去审查自己曾经写下的文件。

工作流一开始运行,载荷就把CI环境内能够到的一切读个遍。CI环境变量。AWS的访问密钥、私钥和会话令牌。GCP的访问令牌。SSH私钥。.npmrc凭据。Docker配置。Kubernetes配置。GitHub Actions的OIDC令牌——它让攻击者能以工作流本身的身份,对该工作流被授权的任何云账户冒名顶替。退出之前,载荷会用grep在仓库源码里搜寻30多种不同的秘密模式(API密钥、密码、证书片段),以防有人把它们粘了进去。AWS IMDSv2、GCP和Azure的元数据端点也会被一并查询,以获取云端的机器身份。

一条把自己的后门发出去的流水线

目前最严重的受害者是Tiledesk——一个开源客户互动平台,它的九个GitHub仓库都遭了殃。5月19日至21日之间,Tiledesk把已内置后门的tiledesk-server包发到了npm上。@tiledesk/tiledesk-server的2.18.6至2.18.12版本如今都带着这段载荷代码,每一个在那个窗口内执行了npm install的下游开发者都把它装上了。这正是Megalodon要的杠杆:在一个开源项目里埋下后门,让它的发布流水线再把后门散播给数以百计的依赖项目。

Black-Iron-Project丢掉了八个仓库。数以百计的小项目(独立开发者账户、大学集群、被遗忘的沙盒)各被波及一两个。攻击者似乎并不挑选目标。模式是覆盖优先于精准:随机八字符用户名的一次性账户,分钟接着分钟地推送着相同的提交信息。C2服务器静静地把回传的内容记录下来。

CI文件为什么逃过了审计

这次攻击之所以成功,正是它将在2026年余下时间里被复演的原因。CI/CD流水线的设计基底就是信任。一个会怀疑下载里某个奇怪二进制的开发者,会毫不犹豫地运行上周才出现在自己仓库里的工作流文件——因为工作流文件的本质就是这个:平台应当执行的代码。审计日志是有的,但很少有团队真的去读。新的提交以build-bot、ci-bot这类名字到来。diff很小。工作流末尾那段base64字符串故意是不透明的。

防御手册简单又让人不快。把5月18日至今碰过任何仓库的每一个秘密都轮换掉。审计管理范围内每个项目的.github/workflows目录。审视那些作者邮箱与任何已知团队成员不匹配的提交。把Actions文件里任何base64二进制块视为有罪,直到解码为止。使用Tiledesk的组织应当回退到2.18.5,或等待一个干净的发布版本。任何在Actions与云服务商之间持有OIDC信任的人,都应当撤销并重新颁发那段信任关系。

Megalodon是这种规模上第一场把CI工作流本身当作软目标对待的活动。它不会是最后一场。这次攻击留下的教训,开发者其实早已用更轻的声音听过:流水线里你没有读的那部分,就是攻击者替你写好的那部分。

讨论

有 0 条评论。