xss.haozi.me靶场通关详解
xss.haozi.me靶场详解
一、模块介绍
1.input code
输入的内容
2.server code
服务端代码,告诉我们程序如何处理输入的内容
3.html
通过处理程序(server code)渲染完的代码
4.浏览器框
显示代码执行结果
二、通关详解
此靶场所有题目都是DOM型xss!
1.0x00
没有过滤,直接输入<script>alert(1);</script>即可成功弹窗
2.0x01
此题将<div>换成了<textarea>,而<textarea>是一个多行文本框,在此标签里输入的内容都会变成多行文本框里的数据,所以需要先将<textarea>闭合
在payload前添加一个</textarea>把标签闭合,即可成功执行后面的xss语句
3.0x02
此题输入点在一个input标签的输入框的value属性中,即在一个当行文本框中输入内容
尝试直接输入payload,发现不能执行(因为输入内容在value属性中,需要先闭合<input>标签)
通过观察发现,只需要在payload前加上一个“>即可将input标签闭合
不使用闭合的方法,使用事件(onmouseover,并将鼠标放在文本框上)也可以通关
4.0x03
此题服务器的过滤使用了正则表达式:
//之间的内容是正则表达式本身(匹配到的内容)
g为全局匹配(一般用于在某一字符串中搜索/替换)
[]为匹配其中字符的任意一个字符(如,[abcd],匹配a或b或c或d)
此题server code的含义为匹配"("或")",并将匹配到的内容替换成空,即只要遇到"("或")"就替换成空(无法输入括号)
所以可以使用其他符号进行绕过过滤,如反引号(波浪线键)等
5.0x04
此题依旧是正则表达式,在上一题的基础上多过滤了反引号
于是我们可以使用编码的方式进行绕过,但是只可以在标签属性(如,scr、onmouseover、value等)中使用编码绕过
使用Unicode编码,将()转化成(),并在两个括号中间加上1即可成功弹窗
此题同样也可以使用onmouseover通关,不过要将<body>换成<input>
真实环境下建议使用onload这种稳定触发的事件
6.0x05
依旧是正则表达式+替换,不过是把匹配内容写进了替换里
由代码可知输入点在一个注释里,且服务器将-->替换成表情防止闭合注释符
但是注释符还有另一个写法:--!>,使用此写法闭合即可成功弹窗
7.0x06
先看此题的正则表达式要匹配什么东西
/auto|on.*=|>/ig
i:不区分大小写
|:匹配前面或后面的内容,如匹配ab/cd则要写成(ab|cd),其中括号用来消除歧义
.*:“.”表示匹配任意字符(除换行符),“*”表示前面的字符可以匹配0次/1次/多次(如:匹配ggle、gogle、google、goooooogle的内容,正则表达式只需要写成go*gle即可),而这两个组合在一起的含义是任何字符的任何长度
此正则表达式含义为:不区分大小写匹配auto或on开头的某个词=或“>”,即匹配事件
由代码可知输入点已经在<input>里面了,输入onmouseover可以显示,但是只要加上=就会被匹配到从而替换成下划线
因为“.”匹配的任意字符不包括换行符,那么我们就使用换行符绕过
8.0x07
先看正则表达式要匹配的内容
</?[^>]+>
\:转义符,匹配后面字符本身
?:表示前面的字符可以出现也可以不出现(出现0次或1次)(如,匹配某url,但不知道是http还是https,即可写成https?😕/xxx.com)
[]特殊用法:若其中有"^",则匹配除[]中字符以外的所有字符
+:表示前面的内容可以出现1次或多次
此正则表达式含义为:匹配</任意字母>或<任意字母>,即匹配html标签
所以,由代码可知,此题不能输入完整html标签,否则会被过滤
因为html语言兼容性强,不完整的标签也可以解析(不输入后面的闭合标签)
此题不能用换行符绕过,因为换行符也是除了“>”外的任意字符
9.0x08
由代码可知正则表达式匹配闭合</style>的标签
<style>标签表示css样式表,不能执行JavaScript语句,即不能直接输入xss语句
像<img scr="xxx">,其中img和src中间有空格,也就是说标签和属性之间是有空格的
</style>标签也是一样的,在style后面加入空格,加入空格后可以往后面加上属性,但是不加属性只加空格也是可以解析的,所以使用空格来绕过匹配
10.0x09
查看正则表达式的匹配内容
^https?😕/www.segmentfault.com
发现没有了开关i和g,表示匹配区分大小写且不是全局匹配
全局匹配的使用:如,在afdsfjkjadf这样一串字符中查找/替换af,正则表达式可以这样写/af/g,对字符串每一个匹配到的内容都进行处理
非全局匹配的使用:验证用户的输入是否匹配某个模板,如验证用户的邮箱是否匹配某个模板,正则表达式可以这样写.*@.*\..*(xxx@8023.io)
:若在整个正则表达式的开头,则表示匹配整个字符串起始的位置,如两个字符串abcd、cdfg,若按照/cd/g进行匹配,这两个字符串都能匹配到,若只想匹配cdfg(顶头匹配),正则表达式需要写成/cd/g,此时就不能再匹配到abcd了
此题正则表达式匹配的是https://www.segmentfault.com或http://www.segmentfault.com开头的网址
所以,必须以上两个url开头才会有显示,先输入其他内容则会显示Invalid URL
我们可以使用onerror事件(访问失败事件)来绕过,去请求url,若请求失败则触发事件(url获取的内容不是JavaScript或者根本获取不到),等待超时后即可触发事件弹窗
11.0x0A
先看代码,下方过滤和上一题一样,但是又增加了新的过滤,将特殊符号替换为实体
所以我们无法使用闭合,只能从url后面想办法
此题可以使用http协议的基础概念,url前面可以添加身份验证信息,如:https://user:pass@www.segmentfault.com(现在用得很少,不安全)
又因为必须以固定的url开头,所以我们把www.segmentfault.com当作身份认证信息,后面再去请求其他域名,如外部js或自己写一个服务器
①使用题目默认的外部js:
拼接好后成功弹窗
原理:实际上访问的网址是后面的xss.haozi.me/j.js,前面的www.segmentfault.com是作为一个身份验证信息传给了xss.haozi.me/j.js
②使用自己写的js文件:
创建一个js文件,写入xss语句
因为是js文件所以不需要写<script>,只有在html页面插入xss语句才需要写<script>
启动一个http服务器(这里我们直接使用phpstudy的服务器)
将https改为http(因为127.0.0.1是http的服务器)
此时载入不成功,因为现在是在一个https页面上引入一个http的内容(在一个安全的页面上引入一个不安全的内容),这是浏览器禁止的行为
我们需要修改设置
成功弹窗
12.0x0B
此题过滤只有一个转为大写
html标签不区分大小写,但是JavaScript语句区分大小写
我们可以引用外部js来弹窗
注:协议和域名都不区分大小写,但是文件区分大小写(haozi内部自带两个文件j.js和J.JS)
本题还可以使用Unicode编码将alert(1);编码来进行绕过
13.0x0C
先看代码,和上一题差不多,但是多了一个把script替换成空
遇到替换成空要想到双写绕过
所以在上一题payload的基础上把script双写即可
也可同上一题使用其他标签+Unicode编码绕过
14.0x0D
查看代码,发现匹配<、/、"、'并替换成空,且输入点在一个script标签的注释里
注:<!-- HTML多行注释 -->
// JavaScript单行注释
/* JavaScript多行注释 */
//为JavaScript单行注释,所以我们可以先换行,又因为已经在script标签内了,就不需要再输入<script>了(不能使用alert('1来闭合后面的'),因为‘会被注释)
但是我们发现alert(1)后面还跟着内容,我们可以换行将其注释掉(-->可以当作html单行注释,不用//和<!--是因为会被过滤)
15.0x0E
查看代码和要匹配的内容
<([a-zA-Z])
():表示分组,如ip为192.168.1.1,使用正则表达式匹配数字,正则表达式为[0-9]+\.[0-9]+\.+[0-9]+,此时想要取出次ip的第二位(168)做后续处理,那么可以在第二位匹配到的位置加上括号[0-9]+\.([0-9]+)\.[0-9]+\.+[0-9]+,然后使用$1取第一个分组匹配到的内容($0为整个正则表达式匹配到的内容本身),也可以这样分组[0-9]+\.([0-9]+\.[0-9]+)\.+[0-9]+,此时$1为168.1
a-zA-Z:表示匹配abc到z所有字母且不区分大小写,等同于[a-z]/i
此正则表达式匹配的内容为”<后一串字符放到分组1中“,替换为"<_$1",如输入<a会将其替换并大写为<_A
所以输入任意html标签都会被替换
我们可以使用特殊字符” ſ “(古英文的小写s),将其转化为大写后就变成了大写的S
然后使用之前的haozi.me自带的外部js即可成功弹窗
也可以使用script执行本机命令
将src写为空,使用onerror,当src接收失败就执行onerror的alert弹窗(因为有转换大写,alert需要Unicode编码)
16.0x0F
由代码可知此题将特殊符号替换为html实体,输入点在onerror中
因为输入点是在标签属性内,即使进行了编码也可以识别(前面有题是用中这个方法绕过的),所以可以直接用单引号进行闭合
17.0x10
此题输入点在window.data中且没有过滤
我们可以先输入空(赋值为空),用分号结束window.data语句,再使用alert弹窗
18.0x11
此题对特殊字符加了两个转义符(\\)
var:在JavaScript中定义变量
console.log(”${s}“):s为我们输入的经过转义的内容
document.createElement('a'):创建一个a元素
a.href = url:a标签(超链接)的属性等于前面定义的url
document.body.appendChild(a):body体添加一个子元素a,即把a标签放进body体中
a.click():点击a标签
所以,我们输入的内容是一个a标签的超链接的内容,并且JavaScript会自动点击这个超链接
首先我们先不去看转义,直接闭合javascript:console.log(" ")
通过");alert("1这样一个语句即可成功闭合
直接复制上去,发现成功弹窗
因为字符串进行一次定义/赋值时,进行一次解转义,不保存转义字符(如:var a = ''8023'',此时a的内容为'8023')
那么,通过代码可知前面已经进行过一次定义赋值了
即进行了一次解转义,在s这里已经少了一个转义符,只剩一个(在html中也可以看到)
而在创建url时又进行了一次赋值,又少了一个转义符
所以,写到标签中的url里已经没有转义符了
因此,这道题不需要管转义符就可以成功弹窗
19.0x12
查看代码,依旧是正则表达式替换,把双引号替换成“\"”
而代码中已经赋值过一次,所以要去掉一个转义符,此时只有一个转义符
我们依旧先不管过滤,直接构造闭合(尽可能不使用双引号,因为过滤的就是双引号,防止出现奇怪的错误)
通过构造");alert(1);//这样的语句进行闭合console.log("");
输入语句后发现,双引号被转义,变成了数据,没能成功闭合
所以我们再在前面加上一个转义符,将代码中用来转义双引号的转义符转义掉,而我们输入的双引号就能成功闭合从而输出后面的alert(1),然后加上分号结束语句(若分号被过滤,可使用加号,做字符串拼接),再用//注释后面的语句
查看元素,打开控制台可以看到,因为我们增加的转义符将代码自带的转义符进行了转义,所以代码自带的转义符变成了数据从而被输出