你驻足于春色中,于那独一无二的春色之中.
先知社区的XSS挑战,不只是过滤的绕过,还需要结合很多浏览器、HTML、CSS、JS的知识点,最后也只做出来9道题~~离2000的ECS还差那么一点点
_(:з」∠)_
完整writeup可以查看先知社区,博客里主要记录我的一些解题思路。
查看源代码可以得知,这里的触发点在文件名
1 | $_FILES["fileToUpload"]["name"]) |
自测的情况下通过抓包修改可以成功弹窗,这道题的难点在于如何把一个self xss变成可以攻击的向量。
当时首先想到了通过中间服务器POST表单进行提交,但是如何在表单中构造文件就成了问题。
1 | <input type='file'> |
作为安全策略,input标签中的文件类型在定义时会生成一个文件对象,而服务端是没有权限来控制这个文件对象的,当然flash是否能够完成对文件对象的控制这里没有尝试,暂时存疑。
无法控制文件对象,那么是否能够通过POST数据来构造一个文件提交呢?
这里又有问题,text型的PSOT数据无法更改文件上传时http头中的boundary,最终还是在先知社区找到了解决方法。
https://xianzhi.aliyun.com/forum/read/224.html
通过<textarea>字段可以伪造文件上传。
在中间服务器上构造form表单,包含<textarea>字段,再使用js自动表单提交。核心代码是这一句
<textarea id="fileToUpload" name='fileToUpload"; filename="<img src=x onerror=alert(1)>121111.gif'>GIF89a hacked.gif</textarea>
这里还有两个点,一个是textarea没有filename字段,所以我们通过闭合引号来伪造,但是firefox和chrome会对双引号进行转义,因此这种方式只能在IE11下成功。另一个点是上传文件进行了文件类型的检测,这里面最容易构造的是gif文件。
触发点在
1 | $_SERVER['HTTP_REFERER'] |
所以需要中间页面来跳转,关于携带refer的跳转方式可以参考这篇博客
http://wps2015.org/2016/06/27/unusual-xss/
这里的问题在于传递后中间refer会被firefox和chrome编码,所以只在win7的IE11中测试成功了。
后来有大牛提到这里可以使用flash做跳转,就可以支持win10的IE,经过测试确实有效。
这道题使用
1 | header("Location: ".$url); |
进行跳转,只有跳转失败,才会执行到触发点上,所以关键问题是如何跳转失败。
这个点过滤了crlf,因此我当时想只能从协议下手,很自然的想到之前被提的较多的gopher协议,所以直接进行测试。
http://ec2-13-58-146-2.us-east-2.compute.amazonaws.com/xss5.php?url=gopher://'><script>alert(123)</script><'
发现没有跳转,能够进入触发点,接下来就是构造传统的payload了。
分析这个点之所以这样,个人猜测是非http协议浏览器在进行执行时策略不同,不一定都是跳转,有的可能是弹框,比如FTP,有的可能是加载相关插件,比如迅雷的下载协议等。
和上一题类似,关键点在于不能让
1 | header('Content-Disposition: attachment; filename="'.$_GET["filename"].'"'); |
执行成功,这里我使用%00%0a进行绕过,还可以通过fuzz去发现更多的bypass手段。
filename=%00%0a1.php&url=http://phantom0301.cc/alixss2.html
绕过后就可以执行到触发点,触发XSS。
这道题有些迷,题目本身通过设置text/plain强制输出文本,我们可以用MIME Sniffing去绕过,我构造了一个iso文件,文件中写入paylaod,在兼容模式下的IE11中可以触发,而小伙伴另一个版本的IE11可以无条件触发。由于需要兼容模式的先决条件,所以这道题当时并不算通过。在这里就不多说了,等待官方writeup。
考察的点是angularJS的模板注入,在两个花括号中angular会解析支持的操作。
网上关于这个点给出的paylaod是
\{\{constructor.constructor('alert()')()\}\}
一共40个字符(忽视我用来转义的斜杠),为什么要数字符数呢?因为这道题的难点在于限制字符只能小于36个。
对于懂angularJS的同学,这道题可能要简单很多,我之前有研究过python的Jinja模板注入,其实两者有很多相似之处。这个点无非是要通过constructor.constructor得到一个匿名函数类型,进而执行弹窗操作,那么突破点就是如何能够构造一个尽可能短的匿名函数类型。
首先,我们要先得到一个JS的变量,为下一步用构造函数得到底层的类型做准备,作为前端小白,只能对照angularJS的手册,一个个尝试,我先后尝试了’’,1,(),[]等多个数据结构,最后找到了如下paylaod
\{\{''.sub.constructor('alert()')()\}\}
刚刚好~~
还是一个利用MIME Sniffing来完成的题。
题目请求url后,需要请求的资源符合所规定的MIME类型,利用这里构造后缀名、文件标识与Content-Type不符合的文件进行请求,在IE11下能够成功弹窗。
http://ec2-13-58-146-2.us-east-2.compute.amazonaws.com/xss12.php?url=http://phantom0301.cc/img/1.avi
其中1.avi的内容如下
1 | <html> |
触发点如下
1 | echo "REQUEST_URI:".$_SERVER['REQUEST_URI']; |
这道题上上面的一道题类似,通过GET变量添加的方式在php文件后面携带paylaod
xss13.php?<script>alert(123)</script>
难点在于input标签是hidden的,因此一些on的事件无法成功触发,同时使用htmlspecialchars过滤标签。
这个在网上可以找到很多类似的讨论,不用再这里细说。
首先使用单引号闭合前一属性,增加accesskey标签,使用onclick标签,这样在firefox下使用Ctrl+Shift+accesskey标签值得组合就可以触发onclick事件。
完整payload如下
1 | ' accesskey=X onclick='alert(document.domain) |
RPO attack
将payload利用绝对路径/相对路径的方式写入CSS文件中,利用IE的CSS样式XSS方法触发弹框,我这里只找到了IE7 IE6成功执行的payload。
div标签中过滤尖括号,同样有很多种绕过手法,我这里使用了和Hideen那道题一样的触发思路:
1 | ' accesskey=X onclick=alert(1) id='xss |
在需要快捷键的情况下触发成功。
真正完成9道题,实现了11道题的弹框。里面大多数题都需要自己去不断尝试,前前后后做了5天左右的样子,头脑风暴的感觉很好,而且几道没有做出来的题都有进一步fuzz测试的思路,可以对XSS整体有了更进一步的了解,而且包括浏览器差异、特殊字符差异等问题也值得去研究探索。