hackweb
appunti di hacking e tecnologia
IT EN
menù principale
menù utente
non sei loggato

JWT: quando la chiave pubblica diventa il segreto

30 giugno 2026 · 3 min di lettura · #web #crypto #authentication

Un JSON Web Token è tre pezzi separati da punti: header.payload.signature, ciascuno in base64url. Header e payload sono JSON leggibili da chiunque — un JWT non è cifrato, è firmato. Tutta la sicurezza sta in un punto solo: che il server, ricevendo il token, ricontrolli che la firma sia valida. È qui che le cose vanno storte.

Difetto 1: alg:none

La specifica JWT prevede un algoritmo chiamato none: significa "token non firmato", pensato per casi in cui l'integrità è garantita altrove. Nell'header:

{ "alg": "none", "typ": "JWT" }

Un token alg:none ha la terza parte vuota. Il problema nasce quando la libreria di verifica legge l'algoritmo dall'header del token stesso e lo asseconda. L'attaccante prende un token qualsiasi, cambia il payload ("role":"user""role":"admin"), imposta alg:none, cancella la firma:

base64url({"alg":"none","typ":"JWT"}) + "." +
base64url({"sub":"1","role":"admin"}) + "."

Se il server verifica con qualcosa come jwt.verify(token) senza vincolare l'algoritmo, accetta il token come "correttamente non firmato". Nessun segreto, controllo di ruolo saltato.

Difetto 2: confusione RS256 → HS256

Questo è più sottile ed è quello che sorprende anche sviluppatori attenti. Servono due nozioni:

  • RS256 è asimmetrico: il server firma con la chiave privata e verifica con la chiave pubblica. La chiave pubblica è, per definizione, pubblica.
  • HS256 è simmetrico: la stessa chiave segreta firma e verifica. È un HMAC.

Immagina un server che si aspetta RS256 ma usa una funzione di verifica generica che sceglie l'algoritmo dall'header e prende come "chiave" lo stesso materiale in entrambi i casi. L'attaccante:

  1. procura la chiave pubblica RS256 (spesso esposta su un endpoint JWKS, in un certificato TLS, o su GitHub);
  2. forgia un token con header alg:HS256 e il payload che vuole;
  3. calcola l'HMAC-SHA256 del token usando la chiave pubblica come segreto HMAC.
import jwt   # PyJWT
public_pem = open('public.pem').read()
forged = jwt.encode(
    {"sub": "1", "role": "admin"},
    key=public_pem,          # la chiave PUBBLICA usata come segreto HMAC
    algorithm="HS256",
)

Il server riceve il token, legge alg:HS256 dall'header, prende la chiave pubblica (che ha già, per verificare RS256) e la usa come segreto HMAC per ricalcolare la firma. Combacia. Il token è accettato. L'attaccante ha firmato un token valido conoscendo solo materiale pubblico.

La radice comune

Entrambi i difetti hanno la stessa causa: lasciare che sia il token a dichiarare come va verificato. Il campo alg nell'header è input dell'attaccante. Fidarsene per scegliere l'algoritmo di verifica è come chiedere al lucchetto quale chiave usare.

La regola che chiude tutto

Vincola sempre l'algoritmo dal lato server, con una lista esplicita, e ignora ciò che dice l'header:

# giusto: il server decide, il token non ha voce in capitolo
jwt.decode(token, key=public_pem, algorithms=["RS256"])

# sbagliato: qualsiasi cosa che non fissi algorithms, o che accetti
# la lista dall'header, o che passi 'verify=False'

Corollari che vale la pena scrivere in ogni checklist:

  • Non usare mai una funzione "verifica e basta" che accetta ogni algoritmo. Molte librerie storiche lo facevano per default; le versioni moderne obbligano a passare la lista, proprio per questo.
  • Tieni separato il tipo di chiave dal tipo di algoritmo: una chiave RSA non deve poter finire in una funzione HMAC. Alcune librerie ora rifiutano esplicitamente questa combinazione.
  • Verifica anche exp, aud e iss: una firma valida su un token scaduto o destinato a un altro servizio non basta.
  • Se puoi, preferisci token opachi lato server (session id + store) quando non ti serve davvero la verifica stateless. Un JWT è una scelta, non un default.

« torna alla home

ultimi post
 
il tuo indirizzo IP:
216.73.216.108
visitatore #0
MOTD:
Ogni astrazione perde da qualche parte.
Qui guardiamo dove.
argomenti