本文是公开报告的摘要与解读,事实以原始报告为准。
2023 年 1 月 4 日,CircleCI 公开披露一起安全事件。1 月 12 日,CTO Rob Zuber 发布正式复盘,确认未授权第三方访问了部分生产系统,并从部分数据库和存储中取走了客户的环境变量、令牌和密钥。报告没有给出受影响客户的总数,只说“少于 5 家客户”告知 CircleCI,其第三方系统出现了与本次事件相关的未授权访问。
CircleCI 的建议很直接:在该时间窗口内把密钥存放在 CircleCI 的客户,应假定这些密钥已被访问;2023 年 1 月 5 日之后写入系统的内容可以视为安全。报告同时把这次事件称为“系统故障”,强调组织性防护,而不是把责任归到某个员工身上。
| 时间 | 事件 |
|---|---|
| 2022-12-16 | CircleCI 一名工程师的笔记本被植入恶意软件;报告称杀毒软件未检出 |
| 2022-12-19 | 攻击者开始侦察;报告称此前没有客户受影响活动的证据 |
| 2022-12-22 | 客户数据被外传;这是生产环境中最后一次被记录到的未授权活动 |
| 2022-12-29 | 客户报告可疑的 GitHub OAuth 活动,CircleCI 与 GitHub 开始联合核查 |
| 2022-12-30 | 确认该客户的 GitHub OAuth 令牌被未授权方取走 |
| 2022-12-31 04:00 UTC | 开始轮换所有客户的 GitHub OAuth 令牌 |
| 2023-01-04 16:35 UTC | 终止被入侵员工的所有访问 |
| 2023-01-04 18:30 UTC | 移除几乎所有员工的生产环境访问权限 |
| 2023-01-04 22:30 UTC | 替换可能暴露的生产主机 |
| 2023-01-05 02:30 UTC | 发送披露邮件并发布公开安全通知(即 1 月 4 日 18:30 PST) |
| 2023-01-05 03:26 UTC | 吊销所有 Project API Token |
| 2023-01-06 05:00 UTC | 吊销 1 月 5 日 00:00 UTC 之前创建的个人 API Token |
| 2023-01-06 06:40–10:15 UTC | 与 Atlassian 协作轮换 Bitbucket 令牌 |
| 2023-01-07 07:30 UTC | 完成 GitHub OAuth 令牌轮换 |
| 2023-01-07 18:30 至 01-12 00:00 UTC | 通过 AWS 通知可能受影响的 AWS 令牌持有人 |
| 2023-01-12 | 正式复盘发布 |
被取走的数据来自“部分数据库和存储”,包括客户环境变量、令牌和密钥。报告使用了“包括”一词,说明这不是一份完整的暴露清单;它也没有给出受影响客户总数,也没有明确声明客户构建、日志或制品未受影响。因此,摘要不应替报告补写“构建完全未受影响”这类结论。
数据在静态存储时是加密的,但攻击者从运行中的进程里取得了加密密钥。报告据此提醒:不能因为数据“加密存储”就认为它没有被访问。对于第三方系统,CircleCI 表示无法判断客户密钥是否被用于未授权访问,只能建议客户按“已泄露”处理并轮换。
报告给出的唯一客户影响数字是“少于 5 家客户”报告了第三方系统的未授权访问;这不是泄露客户总数,而是客户主动告知的数量。下游影响主要体现在凭据轮换:客户需要更新 GitHub、Bitbucket、AWS、SSH 以及 CI 环境中的各类密钥,任何依赖旧凭据的自动化都可能在轮换后失败。
初始入口是工程师笔记本上的恶意软件。报告称该恶意软件没有被杀毒软件发现,它窃取了一个有效的、受 2FA 保护的 SSO 会话,具体机制包括会话 cookie 窃取。攻击者因此可以远程冒充该员工,进入部分生产系统。该员工的日常职责包括生成生产访问令牌,这一权限使攻击者能够进一步访问并取走部分数据库和存储中的数据。
这里的关键不是“2FA 失效”,而是 2FA 保护的是登录动作,不能保护已经被窃取的会话。攻击者不需要再次通过 2FA,只需重放有效会话即可。报告还指出,调查没有发现其他员工的凭据或设备被入侵的证据;它把事件描述为系统性失败,而不是单一个人的疏忽。
从防御角度看,三个条件叠加放大了后果:高权限员工终端被攻破、会话可被远程重放、生产令牌生成权限过于集中。任何一个条件被削弱,攻击者都更难从一台笔记本走到客户密钥库。
CircleCI 的处置分为“切断访问、替换主机、吊销令牌、通知客户、补强控制”几条线。1 月 4 日 16:35 UTC 终止被入侵员工的访问,18:30 移除几乎所有员工的生产访问,22:30 替换可能暴露的生产主机。随后在 1 月 5 日和 6 日分别吊销 Project API Token 与旧个人 API Token,并与 Atlassian 完成 Bitbucket 令牌轮换,1 月 7 日完成 GitHub OAuth 轮换。
补强措施包括:增加 step-up 认证;通过 MDM 和杀毒软件阻断已观察到的恶意行为;增加监控和告警;发布密钥扫描脚本;为 checkout key 增加 SHA-256 签名;在 Contexts API 中增加 updated_at 字段;向免费和付费客户提供审计日志。
对客户,报告建议轮换 OAuth 令牌、Project API Token、SSH 密钥和其他密钥,调查 2022 年 12 月 16 日之后的活动,搜索报告公布的 IP、域名和恶意文件,检查 GitHub 审计日志中的 repo.download_zip 等命令,并考虑采用 OIDC、IP 范围、Contexts 和 runner 等更细粒度的控制。轮换时应先在源系统吊销,再生成新凭据并更新使用方,避免旧凭据在轮换窗口内继续可用。
第一,会话窃取可以绕开 2FA。对高权限工程师的终端,EDR、MDM、磁盘加密、浏览器会话保护和抗钓鱼 MFA 要一起用,不能把 2FA 当成终点。
第二,CI 中的长期密钥是高价值目标。环境变量、Contexts、项目令牌、SSH 部署密钥往往能直接进入生产;能改用 OIDC 短期凭据的,就不应保存长期云密钥。
第三,静态加密不等于访问控制。只要运行中的进程能取出密钥,加密就只能在存储介质被盗时提供有限保护。
第四,检测不能只依赖客户举报。本次事件由客户发现可疑 OAuth 活动后触发核查;对 OAuth 应用、令牌使用和审计日志的异常检测应前置。
第五,轮换是一场跨系统协作。GitHub、Bitbucket、AWS、SSH 和 CI 变量需要在同一张清单上管理,否则“已轮换”可能只是换了一个地方继续暴露。
第六,报告把事故定义为系统失败,这有助于无责复盘;但无责不等于无边界,生产令牌生成权限、终端隔离和最小权限仍要落到工程控制上。
合上页面,先回答,再展开对照。
小程序版
微信扫码,随时查命令