在访问Challenge.intigriti.io 时,显示以下页面
引起我的注意:我看到的第一件事是黑体字,指出XSS仅在Firefox(恰好是我的主要浏览器)中工作。考虑到这一点,我按了CTRL + U来查看页面的静态HTML。这是一个截图:
以下HTML是页面中对JavaScript的唯一引用(当然,不包括可见文本):
<script async src="widgets.js" charset="utf-8"></script>
我看了一下,widgets.js
乍看之下,我看到了一个压缩的JavaScript文件,其中包含对Twitter的一些引用。经过进一步检查,我意识到它可能只是https://platform.twitter.com/widgets.js
的复制和粘贴。我对文件进行了区分,是的,它们基本上是相同的。这时,我只是假设里面的代码widgets.js
是安全的。
尽管其中一个列表条目指出XSS“应在此页面上执行”,但我还是决定四处寻找其他文件。
我在https://challenge.intigriti.io/robots.txt
上看看是否有什么有趣的事情。我确实获得了新的信息,但是没有达到我期望的形式。它只是返回了与以前完全相同的页面。这意味着可以从其他路径访问目标页面,这也很有用。
接下来,我测试了https://challenge.intigriti.io/a/
,结果如下:
那么,这里发生了什么?提供了完全相同的HTML,但是由于URL的路径组件包括一个未转义的/
,浏览器视a/
为目录,并试图从那里加载相对的子资源。换句话说,浏览器正在尝试加载/a/style.css
和/a/widgets.js
而不是/style.css
和/widgets.js
。(顺便说一句,此名称的实际名称是相对的路径覆盖。)
在测试时发现https://challenge.intigriti.io//<location>
是一个开放重定向。例如,https://challenge.intigriti.io//physuru.github.io
重定向到https://physuru.github.io
。另外,访问https://challenge.intigriti.io//
(在两个斜杠之后没有任何内容)没有重定向,而是加载了默认页面。现在,我的目标很明确。我必须让Web浏览器同时使用路径覆盖和开放重定向来加载widgets.js
。
最后使用的一步是路径遍历。 我确实在这部分卡住了一段时间。 我很快发现Firefox和(大多数)其他浏览器之间的区别,但是我不知道如何应用它。区别在于,在Firefox中,如果满足以下条件,则不会删除两个点(..
)和先前的路径组件:
例如,如果要加载https://challenge.intigriti.io/abc/.%2E
(在Firefox中)的任何(合理)变体,则尾随点(以及先前的路径组件)将保留。
根据上面的分析,我们可以结合重定向和路径遍历来解决题目
https://challenge.intigriti.io//physuru.github.io%252fintigriti_may_2020_solution/.%2E
加载https://challenge.intigriti.io/a/.%2E
(在Firefox中)时,我们会得到默认页面(即https://challenge.intigriti.io
页面)!!
这意味着服务器认为我正在请求https://challenge.intigriti.io//
。换句话说,服务器看到了a/
,但是随后看到了.%2E
。将.%2E
被解析为..
,这意味着整个a/.%2E
,URL的一部分基本上忽略(因此不会重定向,而是得到了默认页面)。
但是由于路径遍历仅在服务器端,因此浏览器仍将从//a
中加载相对子资源的目录!因此,浏览器任然向https//a/widgets.js
发出请求,该请求确实被重定向到https://a/widgets.js
。
在https://physuru.github.io/intigriti_may_2020_solution/
的目录下存在widgets.js
。我们可以用
https://challenge.intigriti.io//physuru.github.io%252fintigriti_may_2020_solution/.%2E
来加载JavaScript文件。
%252f
使用的url双重编码,因为还要重定向一次,需要解码两次.
用于重定向的url需要使用https,所以直接使用本地(http)测试不会成功。
如果你想使用github的gists,也不能使用。
参考
https://physuru.github.io/blog/posts/intigriti_may_2020_challenge/