前言
本来该系列只有三篇,而且本篇的一半内容是在《强防御下的XSS绕过思路(三)限制长度》这篇文章里面写的,但是由于设计的题目别人给出了多个我没想到的解法思路,导致最终文章内容的变化,以及文章篇幅等问题,所以就暂且作罢了,相关解析后面就单独写了这篇《强防御下的XSS绕过思路(四)逻辑判断》文章来分享了。
三道题的题目地址如下:
http://px1624.sinaapp.com/test/shortxss.php
http://px1624.sinaapp.com/test/shortxss1.php
http://px1624.sinaapp.com/test/shortxss2.php
其中前两题主要是以长度限制的绕过思路为主进行设计的,第三题的主要难点,是绕过if这个逻辑判断,也是这篇文章讲述的重点。
正 文
1、第一题
http://px1624.sinaapp.com/test/shortxss.php
这个题目其实很简单,根据提示先传个px参数进去
发现会直接把参数内容输出在script里面
那么貌似就很容易了,直接px=alert(2020)应该就可以了。但是仔细去数一数,alert(2020)这是11个字符,上面说限制长度10个字符,所以还是不行。
不死心,去试试,果然没这么简单。
到这里,很多人就不知道怎么弄了。
然后可能就放弃了,其实这些知识,之前在《强防御下的XSS绕过思路(三)限制长度》里面有讲到过,具体方法很简单,就是该文章中提到的“借刀杀人”,利用eval(name)即可。
2、第二题
http://px1624.sinaapp.com/test/shortxss1.php
根据提示把3个参数传进去。
可以看到,分别输出在了img的alt属性以及js代码里面。测试后就会发现,属性里面的参数也都限制了20个字符。所以如果要弹出12345,直接去"onload="alert(12345)是肯定不行的,因为这样会多一个字符出来,长度超过限制。那么直接在js中构造 ';alert(12345);' 这样行不行呢?理论上来说也是不行的,因为看到上面有写,除了双引号基本特殊字符都过滤掉了。
当然我设计这个案例的时候是有一个自己的标准答案的,但是大家的思路往往各式各样,所以我给ID:gainover发过去,看他有没有其他不一样思路,仅仅1分钟后就有了答案,而且和我预想的不太一样。
他的思路是把eval进行重新定义,然后再巧妙的利用js中的可控变量,从而成功执行脚本代码。
不过这个方法有个缺点,因为标签加载成功触发onload的先后顺序,并不一定是按照该标签写入页面的前后顺序执行的,所以会导致这个payload不会100%的触发漏洞。
不过也算是一种别的思路的解法。
然后后面又有人直接给出一个让我惊奇的答案。ID:啦啦
http://px1624.sinaapp.com/test/shortxss1.php?px=';alert(12345);'&px1=1&px2=2
我一看,奇怪?这怎么可以直接用单引号了,我记得我单引号是过滤了啊。打开php源码一看,明明我过滤了啊,但是别人的的确确是用单引号直接突破的。
排查下问题在哪,才发现,原来是strpos这个函数的坑,这个函数在匹配的时候返回的下标是从0开始的,然后匹配不到就直接返回false,然后在代码判断的时候,又存在0==false,所以就尴尬了。只要别人把相关字符放在第一个位置,那么返回的就是0,这个字符就直接默认成白名单可以用的了,所以就直接绕过了。
百度搜了下发现,原来这种坑点,踩的人也蛮多的。
比如这里这个案例 https://xz.aliyun.com/t/2467
然后出现这个问题后,及时改了下代码,将弱判断改成了强判断。
其实很多时候,某些逻辑漏洞的出现,往往就是由于这种弱判断的代码逻辑导致的。
改了代码后,ID:啦啦给出了和ID:gainover一样思路的答案,随后ID: Huuuuu又给出了一个不一样的答案。
http://px1624.sinaapp.com/test/shortxss1.php?px=1&px1=12345%22id=&px2=%22onload=%22alert(alt)
这个思路等于是把2个标签给合并成一个标签了,看到这个答案,我内心有点小郁闷。因为其实这个案例,我是想模拟那些富文本环境或者表单提交环境的XSS组合利用。这种场景下,这些属性基本都是dom写入的,所以肯定不会出现标签被直接穿越的情况。不过由于模拟环境出题的不严谨,等于又被(偷鸡)给出了一个其他思路的解法。所以说,出题貌似比解题感觉要难的多啊。
最后我给出我设计的题目的解法吧。
为什么要这么设计呢?
其实这个思路在《强防御下的XSS绕过思路(三)限制长度》里面也有讲过,就是该文章中提到的“借尸还魂”的方法。
因为在实际情况中,上面ID:Huuuuu的穿越标签的方法肯定是不行的。然后如果想100%触发漏洞,就得这么去构造。利用两次eval,将js变量中的可控参数进行利用,从而最终XSS。
图片img加载,执行onload,然后执行其中的t.alt 这个对应过去就是上面的img里面的eval(px202012) 然后px202012这个变量就是'alert(12345)' 所以等于最终就执行了 eval('alert(12345)') 这个代码。
这里可能有人说为啥不直接eval(px202012)呢?主要还是因为长度问题。这个点也是模拟实战环境,因为实际环境中,网页的可控变量的名字往往会特别长,如果能塞进去当然可以直接eval,如果塞不进去的话,那就需要这样再去中转下了。
本来shortxss就设计了2道题,也是在写《强防御下的XSS绕过思路(三)限制长度》这篇文章的时候,临时写的demo小题作为案例使用的,也是打算直接写入那篇文章的。所以代码写的也比较随意,这也是导致这个第二题,被大家给出了多种不同的答案的原因之一,其实我本意是没有留这些问题BUG点的。
第二题中,因为t.alt这种 id.属性的写法技巧,我灵机一动,又去设计了第三个shortxss小题。这个题目我故意留了些坑(误导解题人思路的),而且也反复验证了下题目设计的严谨性,避免再次被人偷鸡(打脸)。
3、第三题
http://px1624.sinaapp.com/test/shortxss2.php
还是老步骤,第一步看下页面源码。
根据提示把px1和px2两个参数传进去。
发现px1有两处输出,一处在img的alt属性里,一处在js代码的if判断里。px2有一处输出,在js代码的else判断里。
长度都限制在了21个字符,而且过滤了除了双引号的几乎所有特殊字符。如果直接在alt位置构造的话,那么"onload="alert`2012.12.25`这个26个字节,长度是肯定超了的。
那么想着在if位置构造,结果会发现单引号根本就突破不了。
咦?下面有个动态写src的,那我在这里尝试下?
然后测试了就会发现,不管怎么构造,始终都是突破不了src的双引号。这也就是我前面在第二题,穿越标签闭合双引号的那个解法中,提到的实际环境中的属性,基本都是这么写进去的。这种方法去写标签属性,如果你写双引号进去,就会自动被编码掉。
那么上面的位置都不行,难道要在else这位置去入手?
没错,这个题真正考验的就是要突破if判断,执行else这里的代码。其他的输出点有的是辅助点,有的是故意设置的干扰。如果可以执行else代码的话,那么直接 ";alert`2012.12.25`;" 即可。
那么要如何执行这个else呢?从题目判断,只要 document.getElementById("px") 这个不是true,就会执行else的内容。但是明明document.getElementById("px")就是true啊,那么这题岂不是无解?
这里往往思路就陷入到了一个死循环了,可能也有想到这里,但是又会很快的否决掉自己的这个想法。其实方法很简单,要让document.getElementById("px")不是true 那么最直接的方法就是要么px这个id不存在,要么压根连 document.getElementById("px")这个都不存在。
所以也就是覆盖变量、函数的问题了,覆盖px这个id的话,如果说alt属性在id属性之前,那么是可以很容易就做到的,直接 alt=""id="px" 这样就行了。但是这个思路我在设计题目的时候已经注意到了,所以我故意把id这个属性放在了img标签的最前面。那么这个思路不行的话,就只能是去覆盖document.getElementById("px") 这个了。这要怎么搞?其实方法很简单,我先直接给出答案。
为什么就可以了呢?去控制台看看吧。
可以看到,控制台报错document.getElementById不是个函数,那么它现在到底是什么呢?通过控制台去调试,我们发现它现在就是这个name为getElementById的img标签了。
前面第二题里提到了 id.属性的写法,其实有的标签也是可以写成name.属性的,像这里的img就可以。
为什么会这样呢?这是由于非标准化的 DOM 行为,浏览器有时可能会向各种 DOM 元素添加 name 和 id 属性,作为对文档或全局对象的属性引用。但是,这会导致覆盖掉 document原有的属性或全局变量,或者劫持一些变量的内容。
利用这个特性,往往可以绕过一些判断造成XSS,现在这个方法已经有了一个比较专业的名字,叫Dom Clobbering具体的原理和细节,我这里就不在细述了,可以参考这篇文章,写的蛮详细的。
使用 Dom Clobbering 扩展 XSS https://xz.aliyun.com/t/7329
总 结
通过三道比较简单的shortxss小题的思路解析分享,可以看到,这三个题看似简单,但其实都是要求解题者要有着比较扎实的基础,以及需要不断的去变换思路才能搞定的。
后 记
本来这个文章的名字叫《三道shaortxss题目解析和延伸》,但是后面我发现这个标题貌似太普通和随意了,而且这篇文章主要分析的其实是第三题的思路,而且也是在比较强防御下的一种逻辑判断的绕过,所以我就修改了前言内容,并更改了一些其他内容和标题。
第三题的构造,由于必须绕过那个if的逻辑判断,执行else里面的代码,所以如果这点突破不了的话,这个题应该是解不出来的。结果就是截至目前,还没有人成功给出答案。
然后在发稿前,我在思考会不会还有其他我不知道的思路的解法,所以我把该题目发给了ID:gainover让他试试。一分钟后他给出了答案,payload有些不同,但是解法和我设计的答案的思路是一样的,都是覆盖getElementById变量。区别就是他并没有直接写入alert而是用name进行了中转,这样的处理其实更加的合理,因为这样name位置就完全不受长度的限制了。
给出的payload如下:
或者如果其他人有不同的方法,可以将答案发到我的邮箱:px1624@qq.com,说不定下篇你的思路就会被收录了呢。