君は春の中にいる、かけがえのない春の中にいる.

你驻足于春色中,于那独一无二的春色之中.

阿里XSS挑战赛思路及PoC

先知社区的XSS挑战,不只是过滤的绕过,还需要结合很多浏览器、HTML、CSS、JS的知识点,最后也只做出来9道题~~离2000的ECS还差那么一点点
_(:з」∠)_

完整writeup可以查看先知社区,博客里主要记录我的一些解题思路。

0x01 文件上传

查看源代码可以得知,这里的触发点在文件名

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文件。

0x04 referrer

触发点在

1
$_SERVER['HTTP_REFERER']

所以需要中间页面来跳转,关于携带refer的跳转方式可以参考这篇博客

http://wps2015.org/2016/06/27/unusual-xss/

这里的问题在于传递后中间refer会被firefox和chrome编码,所以只在win7的IE11中测试成功了。

后来有大牛提到这里可以使用flash做跳转,就可以支持win10的IE,经过测试确实有效。

0x05 跳转

这道题使用

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,有的可能是加载相关插件,比如迅雷的下载协议等。

0x06 强制下载

和上一题类似,关键点在于不能让

1
header('Content-Disposition: attachment; filename="'.$_GET["filename"].'"');

执行成功,这里我使用%00%0a进行绕过,还可以通过fuzz去发现更多的bypass手段。

filename=%00%0a1.php&url=http://phantom0301.cc/alixss2.html

绕过后就可以执行到触发点,触发XSS。

0x07 text/plain

这道题有些迷,题目本身通过设置text/plain强制输出文本,我们可以用MIME Sniffing去绕过,我构造了一个iso文件,文件中写入paylaod,在兼容模式下的IE11中可以触发,而小伙伴另一个版本的IE11可以无条件触发。由于需要兼容模式的先决条件,所以这道题当时并不算通过。在这里就不多说了,等待官方writeup。

0x10 MVM

考察的点是angularJS的模板注入,在两个花括号中angular会解析支持的操作。

网上关于这个点给出的paylaod是

\{\{constructor.constructor('alert()')()\}\}

一共40个字符(忽视我用来转义的斜杠),为什么要数字符数呢?因为这道题的难点在于限制字符只能小于36个。

对于懂angularJS的同学,这道题可能要简单很多,我之前有研究过python的Jinja模板注入,其实两者有很多相似之处。这个点无非是要通过constructor.constructor得到一个匿名函数类型,进而执行弹窗操作,那么突破点就是如何能够构造一个尽可能短的匿名函数类型。

首先,我们要先得到一个JS的变量,为下一步用构造函数得到底层的类型做准备,作为前端小白,只能对照angularJS的手册,一个个尝试,我先后尝试了’’,1,(),[]等多个数据结构,最后找到了如下paylaod

\{\{''.sub.constructor('alert()')()\}\}

刚刚好~~

0x12 preview

还是一个利用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
2
3
<html>
<img src=x onerror=alert(1)>
</html>

0x13 REQUEST_URI

触发点如下

1
echo "REQUEST_URI:".$_SERVER['REQUEST_URI'];

这道题上上面的一道题类似,通过GET变量添加的方式在php文件后面携带paylaod

xss13.php?<script>alert(123)</script>

0x14 Hidden

难点在于input标签是hidden的,因此一些on的事件无法成功触发,同时使用htmlspecialchars过滤标签。

这个在网上可以找到很多类似的讨论,不用再这里细说。

首先使用单引号闭合前一属性,增加accesskey标签,使用onclick标签,这样在firefox下使用Ctrl+Shift+accesskey标签值得组合就可以触发onclick事件。

完整payload如下

1
' accesskey=X onclick='alert(document.domain)

0x16 PHP_SELF

RPO attack

将payload利用绝对路径/相对路径的方式写入CSS文件中,利用IE的CSS样式XSS方法触发弹框,我这里只找到了IE7 IE6成功执行的payload。

0x17 passive element

div标签中过滤尖括号,同样有很多种绕过手法,我这里使用了和Hideen那道题一样的触发思路:

1
' accesskey=X  onclick=alert(1) id='xss

在需要快捷键的情况下触发成功。

小结

真正完成9道题,实现了11道题的弹框。里面大多数题都需要自己去不断尝试,前前后后做了5天左右的样子,头脑风暴的感觉很好,而且几道没有做出来的题都有进一步fuzz测试的思路,可以对XSS整体有了更进一步的了解,而且包括浏览器差异、特殊字符差异等问题也值得去研究探索。