Analisi dei rischi di violazione dell'autenticazione utente tramite token JWT (JSON Web Token)
Analisi riassuntiva
I ricercatori di Akamai hanno esaminato i token JWT (JSON Web Token) come vettori degli attacchi di violazione dell'autenticazione utente, un tipo di attacco incluso tra i primi 10 rischi per la sicurezza delle API nell'elenco OWASP (Open Web Application Security Project) e hanno scoperto diversi scenari in cui si verificano minacce e tendenze dei token JWT.
Lo standard JWT è responsabile della protezione delle API tramite la trasmissione di token (in genere tra client e server) per la verifica protetta degli utenti. Si tratta di uno dei formati di verifica più diffusi, che contiene informazioni condivise sotto forma di oggetti JSON.
Pur non essendo crittografato, ogni token è codificato e dotato di una firma di verifica. Abbiamo esaminato alcune delle molteplici minacce a cui sono soggetti i token JWT, dovute all'implementazione impropria, o bassa entropia e a chiavi segrete brevi.
Attacchi per il controllo degli account, escalation dei privilegi e fughe di dati sono i tre grossi rischi che le organizzazioni e gli utenti corrono scegliendo i token JWT per le API. Abbiamo notato che nel nostro traffico la maggior parte dei token JWT usa un algoritmo simmetrico, anche se in è in teoria meno sicuro.
In questo post, spiegheremo le best practice per gestire meglio le minacce ai JWT.
Introduzione
I token JWT sono uno schema di token ampiamente diffuso e relativamente facile da attivare che nasconde però molti rischi. Si tratta di minacce che devono essere prese in considerazione al momento dell'implementazione per la salvaguardia dei token stessi. Uno dei rischi più importanti per i JWT, che viene riportato tra i primi 10 rischi per la sicurezza delle API nell'elenco OWASP, è la violazione dell'autenticazione utente.
La violazione dell'autenticazione utente si ha quando l'API non verifica correttamente le credenziali né l'identità dell'utente che invia la richiesta. Purtroppo, questa vulnerabilità, osservata spesso nei token JWT, può portare all'impersonificazione di un utente da parte di un criminale o causare l'accesso all'account di un altro utente, con conseguente escalation dei privilegi e fuga di dati.
Protezione della pipeline
Il token JWT è usato comunemente per l'autenticazione nelle API e nelle applicazioni web. Dal nostro traffico risulta che le applicazioni web adottano sempre più API, con grande tasso di esposizione ai clienti, il che rende necessaria una perfetta autenticazione nei vari endpoint delle API.
L'API è l'ossatura di un'organizzazione, responsabile dei meccanismi di autenticazione e autorizzazione e della ricerca sui database, e può rendere vulnerabili molte funzioni. Per questo motivo le minacce ai token JWT sono più pericolose quando implicano le API. In questo blog, daremo alcune informazioni di base sui token JWT, illustrando sei minacce che li interessano e come aggirarle.
Informazioni di base sui token JWT
Il formato JWT permette di inviare dati JSON firmati per la trasmissione dei dati nelle applicazioni web, mobili e nelle API, in genere usato solo per l'autenticazione. La struttura del JWT consta di tre elementi: l'intestazione (nota anche come intestazione JOSE), il payload e la firma, tutti separati da un punto (Figura 1).
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIiLCJpYXQiOjE2NzYyMTc5NTAsImV4cCI6MTcwNzc1Mzk1MCwiYXVkIjoiYWthbWFpLWJsb2ciLCJzdWIiOiIiLCJjb21wYW55IjoiQWthbWFpIiwidXNlciI6IkFrYW1haS1yZWFkZXIiLCJhZG1pbiI6Im5vIn0.kMPz3Z7BSlBTJKijD8bcrpzTZejX7VCZ77w5oQwJO6I
Figura 1. Esempio dei tre elementi della struttura JWT
Intestazione e payload
L'intestazione e il payload sono raccomandazioni per i campi codificate con protezione URL con Base64 e specifica IETF (Figura 2). Il termine "codificate" significa che non sono leggibili dall'occhio umano, ma sono facilmente decodificate dal server. In questo modo si preserva l'integrità e la fruibilità dei dati, proteggendo al contempo l'URL. Non vengono inoltre a sovrapporsi con i caratteri usati dai browser.
L'intestazione JOSE viene usata sia per la crittografia web (JWE) JWT che per quella JSON, ossia, in sostanza, una JWT crittografata che aiuta a evitare gli attacchi JWT più diffusi. Il campo che indica il metodo di token prescelto è "typ" (typ:JWT/JWE). Il payload potrebbe contenere campi registrati (da parte della Internet Assigned Numbers Authority) o campi personalizzati, a seconda dell'implementazione.
Figura 2. JWT codificato
La firma
Lo scopo della firma è verificare il token, ovvero controllare che il server abbia creato il token e che i dati non siano stati cambiati dal momento della sua creazione.
La creazione della firma comprende due passaggi:
L'applicazione di un algoritmo di crittografia (ad es., MAC) a intestazione e payload, separati da un punto (l'algoritmo usa una chiave segreta)
L'applicazione di un algoritmo di hashing (ad es., SHA256) a intestazione e payload crittografati.
Se si usa JWT, il server verifica la firma per convalidare il token stesso. Spiegherò più avanti gli algoritmi usati per la convalida.
I JWT sono ampiamente diffusi per l'autenticazione nelle applicazioni web per la semplicità d'uso, anche su vasta scala, e di implementazione, e poiché i dati richiesti dal server vengono salvati lato client. Ma ai JWT sono associati dei rischi, anche quando sono firmati. Il token JWT usa testo non formattato e ogni implementazione implica diversi campi del payload. La superficie di attacco e le possibilità di errore sono ampie.
Informarsi su alcune tra le minacce più diffuse e interessanti che devono affrontare i token JWT permette di diventare più consapevoli delle vulnerabilità, rilevare comportamenti dannosi con più rapidità, mitigare i rischi con efficacia e predisporre le misure di sicurezza necessarie a salvaguardarsi da possibili exploit.
Il nostro compito è da una parte offrire agli utenti un approccio più sicuro all'uso dei JWT, dall'altra offrire agli addetti alla sicurezza e agli amministratori gli strumenti e le raccomandazioni necessarie per adempiere alla due diligence.
Sei minacce ai token JWT
1. Uso di token senza convalida da parte dei server
Poiché il JWT è firmato invece che crittografato, prima di ogni uso deve essere convalidato. Nello scenario di rischio più semplice, in cui un'applicazione non esegue la convalida, un malintenzionato potrebbe modificare il payload (ad esempio, l'escalation dei privilegi) e lasciare intonsa la firma o addirittura eliminarlo e ottenere autorizzazioni di livello superiore.
Un altro metodo potrebbe essere usare nell'intestazione il parametro "alg", che rappresenta l'algoritmo usato per firmare il token. Poiché "None" è un valore legittimo (e il token JWT è denominato in tal caso JWT non protetto) chiunque può firmarlo. Anche nel back end c'è una possibile implementazione della verifica JWT.
Basta cercare il campo "alg" nell'intestazione. Poi usare l'algoritmo specificato per verificare il token. L'algoritmo "None" indica che non è necessario firmare e verificare il token. La modifica del payload o dell'intestazione del token in "alg:none" e l'eliminazione della firma consentono di mettere a segno un attacco.
Esempio
La Figura 3 mostra l'esempio di un JWT decodificato.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiZXhhbXBsZSBuYW1lIiwiaWF0Ij
oxNjU5MjM5MDIyfQ.PrhAp2DUWXoL01_odyLATuzrwn5rMtY1IVsP8y4LH5E
decoded:
{
"alg": "HS256",
"typ": "JWT"
}
.{
"name": "example name",
"iat": 1659239022
}
Figura 3. Esempio di JWT decodificato
Presupponiamo che l'endpoint dell'API usi il campo "alg" nel payload per indicare l'algoritmo prescelto per la verifica.
Poniamo di voler modificare il JWT (Figura 4) In questo modo, è possibile creare un JWT valido di un utente diverso
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJuYW1lIjoiZXhhbXBsZSBuYW1lIiwiaWF0Ijo
xNjU5MjM5MDIyfQ.
decoded:
{
"alg": "none",
"typ": "JWT"
}
.{
"name": "other person's name",
"iat": 1659239022
}
Figura 4. JWT modificato in "alg:none".
Best practice Un consiglio semplice: usare sempre un algoritmo predefinito codificato prima di usare il token. Non usare il parametro alg come puntatore dell'algoritmo di verifica.
2. Uso della stessa chiave privata per applicazioni diverse.
Molte aziende scelgono di disporre di registrazioni separate per applicazioni diverse. L'uso della stessa chiave privata crea un token valido in entrambe le applicazioni, ma con un ID utente diverso. In tal caso, basta fare una richiesta a una seconda applicazione con il token della prima applicazione per poter prendere possesso dell'account (non scelto dall'utente) (Figura 5).
Best practice Anche qui la regola è semplice: nel caso di ID utente separati, usare chiavi private diverse.
3. Uso di un algoritmo di firma debole
Esistono due famiglie di algoritmo principali: simmetrici (HSXXX) e asimmetrici (RSXXX,ESXXX,PSXXX). Un algoritmo simmetrico richiede una chiave segreta condivisa; un algoritmo asimmetrico richiede chavi pubbliche e chiavi private (Tabella 1).
Simmetrico | |||
|---|---|---|---|
HSXXX | HMAC + SHA | Algoritmo relativamente debole | Usa una chiave segreta condivisa |
Asimmetrico | |||
RSXXX | RSA + SHA | Algoritmo più sicuro | Usa chiavi private e pubbliche |
ESXXX | ECDSA + SHA | L'algoritmo più sicuro tra i tre | Usa chiavi private e pubbliche |
Tabella 1. Le due famiglie di algoritmi
Dal punto di vista di chi sferra l'attacco, un algoritmo simmetrico può essere attaccato con forza bruta, non richiede la raccolta di chiavi pubbliche e velocizza i tempi di elaborazione. Abbiamo notato nel nostro traffico una presenza maggiore di algoritmi simmetrici rispetto agli asimmetrici (figura 6).
In teoria, gli algoritmi simettrici richiedono meno elaborazioni e su vasta scala hanno performance superiori rispetto a quelli asimmetrici.
Best practice Usare algoritmi asimmetrici. Consigliamo l'uso di algoritmi ECDSA che dal punto di vista della crittografia sono al momento i più sicuri. Una chiave simmetrica adeguatamente protetta è accettabile se la chiave segreta ha un'entropia elevata ed è sufficientemente lunga.
4. Scelta di una chiave privata corta e/o a bassa entropia
Una chiave privata corta e/o a bassa entropia è facilmente soggetta agli attacchi di forza bruta a basso costo. Esistono software di violazione facili da usare installabili negli ambienti cloud ad elevata performance dotati di GPU (Graphics Processing Units). Le performance delle GPU attuali sono in continua crescita, con pesanti ricadute sulle violazioni. Rispetto a tre anni fa, le schede grafiche vengono violate oggi con una velocità superiore di 2 volte e mezzo.
Nella Tabella 2 è riportato il confronto rispetto a tre anni fa sui tempi di violazione di una chiave privata di otto caratteri (a prescindere dal livello di entropia)
Scheda grafica high-end | Giorni necessari a completare la violazione |
|---|---|
Tre anni fa | 10,5 giorni |
Oggi | 4,5 giorni |
Tabella 2. Numero di giorni necessari a violare una chiave privata di otto caratteri
Una chiave privata lunga sette caratteri può oggi essere violata in 90 minuti rispetto alle 24 ore di pochi anni fa. La peculiarità di questo attacco è che viene eseguito offline, senza possibilità alcuna di difesa da parte dell'organizzazione che ne resta totalmente all'oscuro.
Immagina cosa potrebbe fare un criminale sostenuto da un governo capace di creare un sistema a tale scopo. Grazie alla chiave privata potrebbe contraffare un token firmato e assumere le sembianze di qualunque utente semplicemente conoscendone l'ID.
Best practice Scegliere una chiave privata lunga (almeno 10 caratteri) e ad alta entropia. Consigliamo di usare la tecnologia RSA per generare una chiave segreta.
5. Conservare i dati sensibili nel payload del JWT.
I token JWT prevedono la codifica URL Base64 per cui il payload non è crittografato. Memorizzare nomi di DB, ID incrementali (di ogni tipo) o altri dati o campi interni del server espone eccessivamente i dati, che potrebbero essere sfruttati in altri vettori di attacco (es. violazione dell'autorizzazione a livello di oggetto).
Best practice Non memorizzare i dati sensibili in un token JWT. Se necessario, usare piuttosto il formato JWE.
6. Scambio delle chiavi
Negli algoritmi asimmetrici, viene usata una chiave privata per creare il token JWT (la parte della firma) e una chiave pubblica per convalidare il JWT. Un criminale può modificare l'algoritmo specificato nell'intestazione in uno simmetrico (ad es., HS256) e creare una firma usando la chiave pubblica legittimamente impiegata dal server per la verifica.
In questo scenario, il back-end implementato non correttamente userà la chiave pubblica ed eseguirà l'algoritmo simmetrico (secondo quanto specificato dall'hacker nell'intestazione) per verificare il token JWT contraffatto.
Esempio
Nella Figura 7 è illustrato il processo di creazione di un nuovo JWT del server e nella Figura 8 è illustrato il processo di verifica del JWT del server.
Nell'ultima parte della verifica, nel confronto può comparire un errore per uno di questi due motivi (o entrambi):
Intestazione e payload sono stati modificati, ma non la firma
Problema di configurazione dell'algoritmo o della chiave corretti
Nella Figura 9 è illustrato un attacco con confusione delle chiavi.
Ultima fase. Il server verifica il token con il processo illustrato nella Figura 8, in cui si affida al campo alg. Verifica quindi il token eseguendo l'algoritmo HS256 con la chiave pubblica come chiave segreta, secondo quanto previsto dal criminale.
Best practice Usare nel processo di verifica algoritmi predefiniti e non affidarsi all'input dell'utente.
Conclusione
Il token di autenticazione JWT è il più diffuso in circolazione. Consente di usare molte applicazioni web e API grazie all'autenticazione senza accesso frequente. Tuttavia, implica svariati rischi perché non è né crittografato né implementato tenendo presente problematiche di sicurezza.
La capacità di elaborazione informatica è in continua crescita e le chiavi segrete deboli vengono violate in tempi sempre più brevi. Nel caso dei JWT, questo tipo di attacco può avvenire offline all'insaputa delle organizzazioni.
Inoltre, gli algoritmi simmetrici sono i più diffusi, il che facilita la vita dei criminali.
Esistono minacce più complesse, come gli attacchi di autenticazione, che sono però più difficili da rendere automatici. I vettori di attacco JWT, invece, possono essere automatizzati e sferrati in massa.
Per questi motivi, e non solo, è fondamentale che gli utenti siano consapevoli delle vulnerabilità dei JWT e delle best practice a disposizione per la protezione dagli exploit. Ci auguriamo che questa analisi sia una guida utile nella protezione dalle violazioni dell'autenticazione utente, uno dei primi 10 rischi per la sicurezza delle API riportati nell'elenco OWASP.