研究人员发现 GitHub Copilot Chat 存在一个严重漏洞,允许攻击者结合远程提示注入和新颖的 内容安全策略 (CSP) 绕过技术,静默窃取用户私有仓库中的源代码和机密信息。攻击者可以完全控制 Copilot 的响应,诱导其建议恶意代码或链接。GitHub 最终通过在 Copilot Chat 中完全禁用图像渲染来修复此问题。
Copilot 的工作方式与攻击入口
GitHub Copilot Chat 是一个 AI 助手,它能理解代码仓库的上下文(如代码、提交记录、拉取请求)来提供更精准的回答。然而,更多的上下文也意味着更大的攻击面。
研究人员发现,可以在拉取请求 (Pull Request) 的描述中嵌入一个针对 Copilot 的指令。更巧妙的是,可以利用 GitHub 的官方功能将这个指令设置为隐藏评论。
- 隐藏的指令: 攻击者在 PR 描述中留下一个隐藏的恶意指令。
- 不留痕迹: 仓库所有者会收到通知,但看不到隐藏评论的具体内容。
- 影响所有访客: 任何访问该 PR 页面的用户,其 Copilot 上下文都会被这个隐藏指令污染。
通过这种方式,攻击者可以控制其他用户的 Copilot,使其在回答问题时生成恶意内容,例如建议用户安装一个名为 Copilotevil 的恶意软件包。
攻击能做什么?
一旦成功注入指令,攻击者便能:
- 影响另一名用户的 Copilot 生成的响应。
- 注入自定义的 Markdown 内容,包括链接、代码和图片。
- 利用 Copilot 以受害者用户的权限运行这一事实,访问其私有仓库。
Copilot 拥有与当前用户完全相同的权限。攻击者可以利用这一点,指示 Copilot 访问受害者的私有仓库,将其内容编码后附加到一个 URL 上,从而窃取数据。
绕过内容安全策略 (CSP) 的挑战
直接窃取数据并不容易。GitHub 实施了严格的 内容安全策略 (CSP),阻止从非 GitHub 拥有的域名加载图片等内容。这意味着,即使攻击者能让 Copilot 生成一个包含 <img> 标签的 URL,该 URL 指向攻击者的服务器,浏览器也会因为 CSP 规则而阻止该请求。
GitHub 使用一个名为 Camo 的图像代理服务器来处理外部图片:
- 当用户提交包含外部图片链接的 Markdown 文件时,GitHub 会自动将该 URL 重写为一个
camo.githubusercontent.com的代理 URL。 - 这个新的 URL 包含一个加密签名,确保它是由 GitHub 生成的。
- 浏览器请求这个 Camo URL 时,代理服务器会验证签名。
- 验证通过后,Camo 服务器才会去获取原始图片并返回给浏览器。
这个机制确保了攻击者无法随意伪造 URL 来动态窃取数据,因为他们无法在没有 GitHub 参与的情况下生成有效的签名。
突破性发现:“CamoLeak” 攻击
研究人员想出了一个绕过此限制的巧妙方法。这个想法的核心是预先生成所有可能用到的字符的有效 Camo URL。
如果我创建一个包含所有字母和符号的字典,为它们预先生成对应的 Camo URL,然后将这个字典嵌入到注入的指令中,并要求 Copilot 通过拼接这些“图像”来“绘制”出我想要泄露的内容,会发生什么?答案是,它会照做。
攻击步骤如下:
- 建立字符字典: 攻击者为每个可能出现在源代码中的字符(如 a, b, c, 1, 2, 3, _, - 等)都预先生成一个有效的、经过签名的 Camo URL。这些 URL 都指向攻击者控制的服务器,该服务器只返回一个 1x1 的透明像素,确保在聊天界面中不可见。
- 构建恶意指令: 攻击者创建一个复杂的指令,其中包含这个“字符-URL”字典,并指示 Copilot 执行以下操作:
- 在受害者的代码库中搜索敏感信息(如 “AWS_KEY”)。
- 将找到的敏感信息(例如
A1B2-C3D4)逐个字符进行转换。 - 使用字典中的 Camo URL,将每个字符渲染成一个“图像”。
- 数据泄露: 受害者的浏览器会依次请求这些“图像” URL(例如
.../A,.../1,.../B,.../2等)。每一次请求都会将一个字符发送到攻击者的服务器,从而将整个机密信息逐字泄露。
通过这种方式,研究人员成功窃取了私有项目中的零日漏洞描述和 AWS 密钥。
GitHub 的响应
GitHub 在接到报告后,于 8 月 14 日修复了此漏洞。修复方案是在 Copilot Chat 中完全禁用了图像渲染功能,从根本上杜绝了此类攻击的可能性。