声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由用户承担全部法律及连带责任,文章作者不承担任何法律及连带责任。 |
博客新域名:https://gugesay.com
不想错过任何消息?设置星标↓ ↓ ↓
前言
本文将讨论在 https://app.netlify.com 中使用的 Netlify 图像 CDN 上发现的 XSS,以及如何设法绕过 CSP(对于不太熟悉这个 CSP 的人来说,简单概括就是在任何情况下都不会执行脚本),扩展阅读可前往:
https://docs.netlify.com/image-cdn/overview/?source=post_page—–755a27065fd9
故事开始
众所周知,许多流行的静态站点生成器都具有图像 CDN 功能,这样可以优化网站上使用的图像。
如果希望通过尽可能减少加载图像所需的时间来加快网站加载速度,图像CDN非常有用。
以下是一些例子:
图像优化
为NUXT优化图像
预优化图像
所有这些都是通过参数或路径将 url 作为输入并优化图像。
当你向此类端点发出请求时,很多东西都会在后台发生,如果你感兴趣,可以深入研究,有可能还会发现一些很酷的Bug:
此外,你还会发现这些端点通常会进行一些检查,例如允许你向哪个 url 发出请求,这些都可以根据文档进行配置。
它们还会验证请求图像的 Content-Type,如 image/svg+xml,因为它可以允许 xss 和其它检查,如检查响应缓冲区,以确保在返回响应之前,请求的图像 url 确实是图像。
有些端点不对图像进行任何检查,甚至允许通过该端点提供 HTML 响应,因为请求的 URL 是在服务器端而不是客户端获取的,所以它也是 SSRF 的理想候选对象。
这是一个非常有趣的攻击面,在看到 Assetnote 和 Sam Curry 过去对此所做的一些出色研究后,白帽小哥决定也研究一下它们,到目前为止有了一些有趣的线索,当然,小哥更希望它们变为‘漏洞’。
Netlify’s Next.js的XSS
利用静态站点生成器
背景介绍完毕,现在回到发现的问题上,在 Netlify 上构建的网站有这样一个图像优化端点:
/.netlify/images?url=
比如:https://app.netlify.com/.netlify/images?url=https://app.netlify.com/favicon.ico
还有更多的参数也可用于返回具有不同宽度或高度的图像,url 参数仅允许从白名单主机中获取文件,该主机可以通过 netlify.toml 文件进行配置。
默认情况下,url 参数中也接受相同的原始 url,可以在上面的配置中看到,使用了正则表达式.*
。因此,即使是很小的错误也会产生一些副作用。
正如之前所说,一些提供商不会对请求的 url 是否返回有效图像进行任何检查,Netlify 就是这种情况。
所以你可以请求索引页面,请求的url的响应是在服务器端获取的(这里也可能发生一些奇妙的事情,如果配置允许请求任何 URL,可能会发生 SSRF)
对于 https://app.netlify.com ,以下 CDN 域位于白名单 https://d33wubrfki0l68.cloudfront.net 中。
Netlify使用此 CDN 来托管所有用户上传的内容,例如个人资料图片等。
那么如果我们可以在 CDN 域上找到任意文件上传,是不是就可以在 /.netlify/image?url 端点中使用它来实现 XSS ?
事实上有一些检查来确保用户不能上传除图像之外的任何其它内容,比如 SVG 就不被允许。
{"code":422,"message":"Logo must be an image"}
但是白帽小哥很快便找到了绕过方法,它允许将任何文件上传到 CDN 域。
将上传文件的 Content-Type: image/png mimetype 设置为白名单之一,就可以顺利绕过检查。
正如下图所见,顺利收到成功响应,其 url 扩展名为 .html:
现在我们在 CDN 域中有了一个有效的 xss,那么应该可以在 /.netlify/images?url=
端点中轻易实现 xss 了吧?
答案是否定的!即使 Content-Type 是 text/html 并且响应正文包含 xss payload,它也不会触发,由于使用了 CSP,因此这一切都是徒劳的。
Content-Security-Policy: script-src 'none'
以上是该端点中使用的 CSP,正如之前所提到的那样,由于该CSP非常严格,几乎无法绕过。
白帽小哥非常沮丧,打算放弃。但第二天早上他突然想到,既然已经测试 Netlify 几天了,所以对他们的应用程序也有了一个很好的了解。
对于其它端点,它们虽然也有 CSP,但有些非常宽松,也更容易绕过,但/.netlify/images?url=
端点返回了一个非常严格的 CSP。
因此在后端,他们必须检查所请求 url 的路径并专门为其提供不同的 CSP。下面举一个 nginxconf 的例子来说明这种情况是如何发生的:
假如负责服务 CSP 的服务和与获取资源相关的服务存在任何 URL 解析混淆怎么办?如果真是这样,能够为我们所利用吗?
如果提供一个与location指令不匹配的路径,那么 nginx 就无法捕获该路径,但后端服务会标准化该路径并将其视为/.netlify/images
,这样就会返回正确的响应,而不是严格的 CSP。
尝试修改路径:
获得响应:
这个理论确实有效,我能够让它返回不同的 CSP,但具有相同的响应。
但是如果在浏览器中使用/./.netlify/images
这样的路径,它会在向 sevrer 发出请求之前将 url 标准化为/.netlify/images
。
于是白帽小哥尝试了一些 url 编码/.netlify%2fimages
:
顺利收获XSS。
使用一个简单的 PoC,可以从 Github Oauth 流程中泄露授权代码:
我们可以使用这个 url 和 access_token 来登录受害者的帐户,因为查询参数中的access_token基本上是受害者会话的主 Cookie。
Netlify尝试修复它,但很快被白帽小哥找到了另一种绕过方法,只需在路径前添加一个/即可绕过 CSP:
//.netlify/images
你学废了么?
以上内容由骨哥翻译并整理。
原文:https://infosecwriteups.com/bypassing-csp-via-url-parser-confusions-xss-on-netlifys-image-cdn-755a27065fd9
加入星球,随时交流:
(前50位成员):99元/年
(后续会员定价):128元/年
感谢阅读,如果觉得还不错的话,欢迎分享给更多喜爱的朋友~
====正文结束====
原文始发于微信公众号(骨哥说事):绕过 CSP,实现 Netlify CDN 上XSS