文章目录
靶场:https://xss.pwnfunction.com/challenges/ww3
代码
<!-- Challenge -->
<div>
<h4>Meme Code</h4>
<textarea class="form-control" id="meme-code" rows="4"></textarea>
<div id="notify"></div>
</div>
<script>
/* Utils */
const escape = (dirty) => unescape(dirty).replace(/[<>'"=]/g, '');
const memeTemplate = (img, text) => {
return (`<style>@import url('https://fonts.googleapis.com/css?family=Oswald:700&display=swap');`+
`.meme-card{margin:0 auto;width:300px}.meme-card>img{width:300px}`+
`.meme-card>h1{text-align:center;color:#fff;background:black;margin-top:-5px;`+
`position:relative;font-family:Oswald,sans-serif;font-weight:700}</style>`+
`<div class="meme-card"><img src="${img}"><h1>${text}</h1></div>`)
}
const memeGen = (that, notify) => {
if (text && img) {
template = memeTemplate(img, text)
if (notify) {
html = (`<div class="alert alert-warning" role="alert"><b>Meme</b> created from ${DOMPurify.sanitize(text)}</div>`)
}
setTimeout(_ => {
$('#status').remove()
notify ? ($('#notify').html(html)) : ''
$('#meme-code').text(template)
}, 1000)
}
}
</script>
<script>
/* Main */
let notify = false;
let text = new URL(location).searchParams.get('text')
let img = new URL(location).searchParams.get('img')
if (text && img) {
document.write(
`<div class="alert alert-primary" role="alert" id="status">`+
`<img class="circle" src="${escape(img)}" οnlοad="memeGen(this, notify)">`+
`Creating meme... (${DOMPurify.sanitize(text)})</div>`
)
} else {
$('#meme-code').text(memeTemplate('https://i.imgur.com/PdbDexI.jpg', 'When you get that WW3 draft letter'))
}
</script>
限制为
- 弹出一个 .alert(1337)sandbox.pwnfunction.com
- 没有用户交互。
- 不能使用 。https://sandbox.pwnfunction.com/?html=&js=&css=
img作为img标签的src属性被写入,且被过滤了关键符号。
text作为文本被渲染,渲染前都经过一次DOMPurify.sanitize处理
从代码中,我们可以看到一个JavaScript生成的HTML页面,包含用于生成图片和文字的meme模板,以及一个使用DOMPurify
来清理输入的防护机制。
分析代码
-
memeTemplate
函数: 用于生成包含图片和文本的meme模板,使用了用户传入的img
和text
参数,模板中有一些样式和布局定义。 -
输入过滤:
escape
函数用于清理用户传入的img
和text
,去掉了<
,>
,'
,"
,=
等可能用于XSS攻击的字符。DOMPurify.sanitize()
用于防止插入恶意HTML或JavaScript。
-
主逻辑:
- 通过
URL
的参数text
和img
生成meme。如果这两个参数存在,会使用模板生成一条警告,并在图片加载完成后触发memeGen
函数,最终显示meme。
- 通过
挑战目标
挑战的目的是在不与页面进行交互的情况下触发一个alert(1337)
。需要绕过现有的防护措施,比如escape
和DOMPurify.sanitize
,这两个工具通常会防止注入恶意代码。
绕过方法
-
可能的攻击向量:
escape
只去除了几个特定字符,其他的字符可能被忽略。- 在
img
标签中,当图片加载完成时,memeGen
函数会被触发,并且不会对图片的实际内容做进一步验证。
-
利用事件属性:
-
我们可以尝试使用其他事件属性,如
onerror
,因为onload
会在图片成功加载时触发,而onerror
在图片加载失败时触发。 -
escape
不会过滤冒号(:
),因此可以尝试使用javascript:
协议在图片URL中插入恶意代码。
-
解决方案
我们可以在img
参数中注入一个无效的图片URL,并利用onerror
来执行JavaScript代码。
payload
?img=https://i.imgur.com/PdbDexI.jpg&text=<img%20name%3dnotify><style><style%2F><script>alert(1337)%2F%2F
关键部分:
-
img=https://i.imgur.com/PdbDexI.jpg
:- 这是一个合法的图片URL,加载时不会触发
onerror
,确保图片可以正常显示并调用页面中的逻辑处理。
- 这是一个合法的图片URL,加载时不会触发
-
text=<img%20name%3dnotify><style><style%2F><script>alert(1337)%2F%2F
:text
参数中的内容包含了<img name="notify">
、一个嵌套的<style>
标签关闭和一个嵌套的<script>
标签。- 关键在于这个
<style><style/>
和<script>alert(1337)//
部分。
如何绕过过滤机制
escape()
函数用来去掉<
,>
,'
,"
,=
等字符,但它不会对/
,%
等符号进行处理。- 通过URL编码(即
%20
表示空格,%3d
表示=
)成功混淆并避开了过滤机制的限制。
输入解析过程:
escape()
函数去掉部分特殊字符后,text
参数在页面中仍然保留了有用的HTML结构:<img name=notify>
:这是一个有效的img
标签,它本身不会执行任何恶意代码。<style><style/>
:嵌套的style
标签被浏览器解析为一个标签的结束,而后一个标签未关闭(<style/>
),实际上结束了样式声明的范围。<script>alert(1337)//
:接下来,是一个<script>
标签,紧随其后的alert(1337)
会被执行,后面的//
是JavaScript注释符,注释掉后续代码防止报错。
为什么这段代码会执行?
浏览器的宽容性解析
- 浏览器对不规范的HTML有一定的容错能力。虽然
<style>
标签是嵌套的,它最终会被解析为合法的样式标签闭合。后续出现的<script>
标签会被浏览器认为是一个合法的JavaScript块,从而执行其中的alert(1337)
。
绕过DOMPurify
的清理
- 使用的
<img name=notify>
和嵌套<style>
标签没有被DOMPurify
清理掉。这是因为它们被认为是普通HTML标签,符合预期的内容格式。 DOMPurify
主要会清理尝试注入的危险内容(如<script>
标签),但它可能忽略了嵌套的情况,尤其是在<style>
标签后紧跟的<script>
标签。浏览器在解析这些HTML时,会按照顺序处理,最终执行<script>
标签中的JavaScript。
涉及的安全漏洞与技术知识
XSS (跨站脚本攻击)
- 成功触发的是一种经典的XSS攻击,通过将恶意JavaScript代码注入到网页中,使其在用户的浏览器中执行。这种攻击类型广泛用于窃取用户信息、会话劫持、恶意重定向等。
HTML的容错机制
-
浏览器对不完全规范的HTML有很大的容错性。比如,嵌套的
<style>
标签本来是无效的,但浏览器会自动关闭外层<style>
,继续解析内部的标签。 -
这个宽容的解析机制让
<script>
标签成功执行,因为浏览器自动处理了<style>
标签的闭合,并解析出了有效的<script>
块。
DOMPurify绕过
-
DOMPurify
是一个用来防止XSS攻击的工具,它的工作机制是通过清理危险的HTML标签和属性来确保页面安全。然而,在某些复杂的情况下,它可能会被绕过。 -
本例中,嵌套的
<style>
与<script>
标签巧妙地利用了DOM解析的特性,使得DOMPurify
没有完全过滤掉后续的<script>
标签。
总结
- 利用了浏览器对HTML和CSS解析的容错性。
- 巧妙地利用了嵌套的
<style>
和<script>
标签,让过滤器漏掉了恶意代码。 - 通过混淆和编码的手段避开了部分过滤机制,使得恶意代码最终在用户的浏览器中执行。
这是一种典型的基于XSS的攻击,展示了如何通过不同方式绕过安全措施执行JavaScript代码。