Vai al contenuto
Token security

OWASP JWT: brute-force su 10.000 secret + kid injection

Incolla un token JWT e ottieni in pochi secondi un audit security-first: rilevamento di alg=none e permutazioni (NoNe, NULL, alg numerico), brute-force di un secret HS256 contro un dataset di 10.000 secret noti (wallarm/jwt-secrets + SecLists, ricompilato giornalmente), alg confusion attack (HS256 firmato con la pubkey RSA del backend) quando fornisci la pubkey, claim RFC 7519 mancanti (exp, iat, aud, iss, jti), lifetime sospetto, header kid con caratteri da injection, jku e x5u senza pinning, header esoterici (cty, zip) usati come pivot. L'analisi gira interamente nel browser via WebCrypto: il token non lascia mai la pagina.

Trascina qui un file .jwt o .txt che contiene il token, oppure clicca per selezionarlo (max 5 MB)
Pubkey opzionale per alg confusion check

Se il token e\' HS256 e tu fornisci la public key RSA del backend, il tool tenta la verifica HMAC usando la pubkey come secret. Se passa, hai un finding critical di alg confusion: il backend accetterebbe token HS256 firmati con la sua stessa public key. Se non hai la pubkey, lascia il campo vuoto e il check viene saltato.

Come usare l'audit

  1. 1

    Recupera un JWT

    Tipico flow: cattura il token dalla request HTTP del browser (DevTools > Network > header Authorization: Bearer...), oppure da log applicativi, oppure da copia diretta dell'output del tuo identity provider in fase di test. Per analisi assistita: salva il token in un file .jwt o .txt e usa il dropzone per caricarlo direttamente.

  2. 2

    Incolla il token (e opzionalmente la pubkey)

    Tre parti separate da punto: header.payload.signature. Il tool valida il formato base64url e fallisce con messaggio diagnostico se uno dei segmenti è malformato. Se vuoi testare l'alg confusion attack: apri la sezione "Pubkey opzionale" e incolla la public key RSA del backend (PEM o JWKS). Senza pubkey il check di alg confusion viene saltato; gli altri 15+ check funzionano comunque.

  3. 3

    Esegui l'audit

    Bottone Audit per il check di default (test contro 1.000 secret più comuni del dataset wallarm/SecLists, completa in <1 secondo). Bottone Audit profondo per estendere il brute-force a 10.000 secret (5-10 secondi, tipicamente da usare quando il check rapido non ha trovato match e vuoi escludere il vettore con maggior coverage).

  4. 4

    Leggi il report

    Output a tre livelli. Header e payload decoded in alto (visibili full-text per ispezione manuale dei claim). Findings ordinati per severity: critical, high, medium, low, info. Score aggregato 0-100. Per ogni rilievo: descrizione tecnica del vettore, riferimento normativo (CVE, RFC, OWASP), remediation suggerita.

  5. 5

    Esporta o stampa

    Copia report: text plain per ticket interni o documenti di audit. Esporta per chatbot: markdown completo con context del tool, findings dettagliati e prompt template, da incollare in ChatGPT/Gemini/Claude per priorizzare la remediation o stimare gli sforzi di fix. Stampa del browser per export PDF (CSS print-ottimizzato che nasconde nav e CTA).

Vettori di attacco JWT, perché un audit di triage statico ha senso

Il rischio reale dei JWT viene dalla configurazione, non dal formato. Leggere il payload di un token (cosa fa il JWT decoder) è la parte facile: chiedersi se quel token è esposto a uno dei pattern noti di compromissione è ciò che separa un'integrazione production-grade da un incidente in attesa di accadere. Le CVE storiche su librerie JWT diffuse (jsonwebtoken < 8.5, jose < 4, python-jwt, ruby-jwt) sono tutte conseguenza di assunzioni implicite del backend che il tool fa emergere dal solo manifest del token.

I quattro vettori classici verificati dall'audit. (1) alg=none e permutazioni: librerie storicamente vulnerabili accettavano header {"alg":"none"} bypassando la verifica. Il check copre la stringa esatta e tutte le permutazioni di case (None, NONE, nULL, null, alg vuoto, alg numerico, alg mancante). (2) HS256 con weak secret: HMAC con secret condiviso brute-forzabile offline se il secret è una passphrase umana. L'audit prova un dataset curato di 10.000 secret comuni (wallarm/jwt-secrets + SecLists/scraped-JWT-secrets, ricompilato giornalmente) verificando ogni candidato via WebCrypto HMAC-SHA256 in locale. (3) alg confusion attack: il backend è configurato per RS256 ma accetta anche HS256, e usa la public key RSA come secret HMAC. Vettore documentato in CVE storiche (jsonwebtoken pre-8.5). Se fornisci la public key, il tool tenta la verifica HMAC con la pubkey come secret e segnala critical se passa: significa che il backend accetterebbe token attacker-controllati firmati con la sua stessa public key (chiave pubblica per definizione). (4) kid injection / jku-x5u abuse: header che dichiarano la chiave da usare per la verifica. Se il backend non li sanitizza (kid usato come key path o lookup SQL) o non li pinna a domini fidati (jku/x5u), un attaccante che controlla l'input controlla la chiave.

Claim mancanti. RFC 7519 definisce claim opzionali con valore di sicurezza concreto: exp (expiration, scadenza temporale), nbf (not before, ritardo di attivazione), iat (issued at, timestamp di emissione), jti (JWT ID, anti-replay), aud (audience, mitigazione del confused deputy attack), iss (issuer, mitigazione del rogue IdP). Anti-pattern frequente: token senza exp, che vivono per sempre senza possibilità di revoca server-side né rotazione automatica; oppure senza aud, che il service A può inoltrare al service B che lo accetta perché coperto dallo stesso identity provider, anche se non era destinato a lui.

Header esoterici. Due header meno noti che il tool segnala come info: cty (content type, abilita nested JWT - un JWT dentro un JWT, vettore di confusione se il backend lo de-wrappa senza riautenticare), zip (compression: l'header {"zip":"DEF"} abilita la decompressione DEFLATE del payload, ed è stato vettore di attacchi reali via zip bomb su librerie che non limitavano la dimensione output).

Privacy operativa. Il token JWT contiene il payload con i claim utente e l'header con la configurazione di firma: in audit reali non vuoi caricarlo su un servizio terzo, anche con TLS. Qui non parte nessuna richiesta di rete con i dati del token. Il dataset di secret (10.000 entries, ~180 KB raw) viene scaricato dal browser una sola volta al primo utilizzo e cachato in localStorage per le sessioni successive (invalidazione automatica via SHA-256 sul file pubblico). Audit, parsing del JWT, verifica HMAC, brute-force sui secret, lettura della pubkey: tutto in locale via WebCrypto API.

Quando il triage statico è il livello giusto. Casi tipici. (a) Review preliminare di un'API legacy senza accesso al backend: hai catturato un token dal frontend e vuoi capire se la configurazione lato server è solida. (b) Pre-engagement audit per stimare lo sforzo di un eventuale incarico di hardening JWT prima di firmare il preventivo. (c) Screen iniziale prima di un assessment cyber serio: la lista dei high/critical va approfondita con esercizio di exploitability assessment, mappatura dei codepath di verifica nel backend, verifica della whitelist di algoritmi accettati e del pinning JWKS. (d) Self-check periodico per il proprietario dell'API che vuole sapere se l'integrazione è stata fatta a regola d'arte.

Limite di scope. L'audit non sostituisce: una review architetturale del flusso completo (rotazione delle chiavi, refresh token rotation, logout server-side con blacklist jti, audience binding, gestione del kid e jku/x5u in produzione, configurazione del provider OIDC); l'analisi statica del codice di verifica nel backend (whitelist algoritmi, leeway sull'exp, gestione delle eccezioni); lo studio del threat model specifico dell'applicazione. È un triage e si propone come tale.

Cosa controlla esattamente

L'audit applica 18 check distribuiti su 4 famiglie. Tutti i check girano in locale nel browser via WebCrypto (per le verifiche HMAC) e via parsing JSON puro per gli altri.

Famiglia 1 - Algoritmo (4 check). alg_none verifica la stringa esatta none in qualsiasi case. alg_permutation copre le varianti malevole: alg vuoto, alg numerico, alg null JSON, alg NULL/None/NoNe/nULL. alg_confusion_confirmed (richiede pubkey opzionale): se il token è HS256 e l'utente ha fornito una public key RSA, il tool tenta una verifica HMAC-SHA256 usando la pubkey come secret. Se la verifica passa, il backend accetta token HS256 firmati con la sua public key (chiave pubblica per definizione). Vettore confermato. weak_secret: bottone Audit = test contro tier fast (1.000 secret comuni, <1s); bottone Audit profondo = test contro tier full (10.000 secret aggiuntivi, 5-10s).

Famiglia 2 - Header esoterici (4 check). kid_suspicious: il valore di kid contiene caratteri tipici di path traversal (../) o SQLi (UNION, SELECT, OR, AND, --, '). jku_present e x5u_present: header che dichiarano la URL di una public key esterna; senza pinning whitelist, l'attaccante che controlla la URL controlla la chiave (HIGH). typ_missing: assenza di typ, raccomandato da RFC 7519 par. 5.1. cty_present e zip_present: header che abilitano nested JWT e DEFLATE, segnalati come INFO per ispezione manuale del codepath.

Famiglia 3 - Claim del payload (8 check). Per ogni claim RFC 7519 rilevante: presenza, formato, valore. exp_missing: token senza scadenza (HIGH). exp_expired: scadenza nel passato (INFO, mitigazione attiva). exp_far_future: exp > 1 anno nel futuro (MEDIUM). iat_missing: assenza di issued-at (LOW). lifetime_too_long: exp - iat > 30 giorni (HIGH, configurabile). aud_missing: nessun audience binding (MEDIUM, confused deputy). iss_missing: nessun issuer (MEDIUM, rogue IdP). jti_missing: nessun anti-replay ID (LOW).

Famiglia 4 - Brute-force HS256 (1 check, 2 modalità). Implementazione: il browser importa via crypto.subtle.importKey ogni candidato come HMAC key, calcola la firma del segmento header.payload via crypto.subtle.verify, confronta con la signature presente nel token. Sequenziale (HMAC-SHA256 su input piccolo non beneficia di parallelismo browser). Throughput tipico: 1.000-2.000 verify/secondo su laptop moderno. Tier fast 1.000 secret = sub-secondo. Tier full 10.000 secret = 5-10 secondi. Il dataset è ricompilato ogni notte da shared/cron/build_jwt_secrets_db.php tramite union(wallarm, SecLists), dedup case-insensitive, cap a 10.000 entries (gli oltre 90.000 della long tail vengono droppati: dopo i primi 10k il match rate aggiuntivo è marginale e il costo browser non lo giustifica).

Atomicità delle pubblicazioni. Il job cron applica una scrittura atomica multifile: i tier vengono scritti su file temporanei, rinominati uno per uno, e l'index.json con i nuovi SHA-256 è l'ultimo file rinominato. Se il processo muore a metà, i client continuano a leggere il dataset precedente. Mai dataset parziale. Se le sorgenti upstream falliscono, il job aborta senza pubblicare: meglio dataset vecchio di un giorno che dataset incompleto.

Come si legge un report

Punteggio aggregato 0-100. Calcolato come 100 - somma(severity_weights), dove i pesi sono: critical 50, high 20, medium 10, low 5, info 0. Lettura: 80-100 verde (postura ragionevole), 50-79 giallo (interventi pianificabili), 0-49 rosso (rischio significativo, alcuni vettori richiedono mitigation immediata). Il punteggio non misura la qualità del backend complessivo, solo la postura del singolo token rispetto ai pattern OWASP/CVE noti.

Severity dei finding. critical: vettore confermato che permette forgery o bypass di firma diretto (alg=none accettato, alg confusion verificato, secret HS256 trovato nel dataset). Mitigation immediata. high: vettore probabile ma non confermato dal solo manifest (jku/x5u senza poter verificare il pinning lato backend, secret weak in tier non testato, lifetime troppo lungo, exp missing). Da approfondire e mitigare in sprint corrente. medium: pratica subottimale che riduce le difese in profondità (aud/iss missing, kid suspicious, exp far future). Backlog di hardening. low: best practice mancata (iat/jti missing). Cleanup quando opportuno. info: stato osservazionale (typ missing, exp expired, cty/zip present). Reporting only.

Cosa fare in concreto, per priorità. (1) alg=none / alg permutation CRITICAL: il backend deve rifiutare esplicitamente tutti i valori di alg fuori da una whitelist (HS256, RS256, ES256). Patch immediata, test di regressione con token malformati. (2) alg confusion confermato CRITICAL: il backend deve usare API con verifica per algoritmo specifico (es. jwt.verify(token, key, { algorithms: ['RS256'] }) in jsonwebtoken), non auto-detect dell'algoritmo dall'header. (3) weak secret HIGH/CRITICAL: ruotare immediatamente il secret a una stringa casuale crypto-safe da 32+ byte (openssl rand -base64 32) e invalidare tutti i token in circolazione. (4) jku/x5u HIGH: il backend deve pinnare la URL whitelist o ignorare completamente questi header e usare solo JWKS endpoint hardcoded. (5) kid suspicious MEDIUM: validare kid contro whitelist alfanumerica, lookup esatto in mappa interna, mai usarlo come parametro di query SQL o file path. (6) claim missing: aggiungere exp, aud, iss, jti al template di emissione del token. Validare lato server con leeway ragionevole (5-30 secondi).

Format del finding alg confusion. Quando il check passa con la pubkey fornita, il finding riporta: il token, la public key usata come secret, l'algoritmo dichiarato nell'header, una descrizione testuale del vettore. Da girare al team con il messaggio operativo: "il backend deve verificare il token con l'algoritmo specifico atteso, non con quello dichiarato dall'header. Patch suggerita: vincolare l'algoritmo nella signature di verify, oppure rifiutare HS256 a livello applicativo se l'architettura usa RS256".

Tabella sintetica dei check applicati

CheckSeverityRiferimento
alg=none / alg=None / alg=NONE / alg=nullCriticalCVE-2015-9235 (jsonwebtoken < 8.5), CVE-2018-7651 (jose < 4)
alg permutation (case-mix, vuoto, numerico)CriticalOWASP JWT Cheatsheet
alg confusion confermato (HS256 con pubkey RSA come secret)CriticalCVE-2016-10555, OWASP JWT Cheatsheet
HS256 con secret nel tier fast (1.000 più comuni)CriticalOWASP JWT Cheatsheet
HS256 con secret nel tier full (1.001-10.000)HighOWASP JWT Cheatsheet
exp mancanteHighRFC 7519 sec. 4.1.4
exp già scadutoInfoRFC 7519
exp oltre 1 anno nel futuroMediumOWASP JWT Cheatsheet
iat mancanteLowRFC 7519 sec. 4.1.6
aud mancanteMediumOWASP confused deputy
iss mancanteMediumOWASP rogue IdP
jti mancanteLowRFC 7519 sec. 4.1.7
Lifetime > 30 giorniHighOWASP JWT Cheatsheet
kid presente con caratteri sospetti (path/SQLi)MediumOWASP Injection Cheatsheet
jku presenteHighOWASP JWT spec abuse
x5u presenteHighOWASP JWT spec abuse
cty presente (nested JWT)InfoRFC 7519 sec. 5.2
zip presente (DEFLATE)InfoRFC 7516 sec. 4.1.3
typ mancanteInfoRFC 7519 sec. 5.1

Glossario

Termini tecnici usati in questa pagina, spiegati in due righe.

JWT #
JSON Web Token, RFC 7519. Stringa formato header.payload.signature, ogni segmento base64url-encoded. Contiene claim JSON sull'identità o sull'autorizzazione. Standard de facto per API authentication moderne (OAuth2, OpenID Connect).
JWS / JWE #
JWS (JSON Web Signature, RFC 7515) = JWT firmato, payload in chiaro base64url. JWE (JSON Web Encryption, RFC 7516) = JWT cifrato, 5 segmenti invece di 3, payload non leggibile senza chiave. Questo audit gestisce JWS classico (firmato, payload leggibile).
alg=none #
Valore dell'header alg che indica firma assente. RFC 7518 par. 3.6 lo definisce come opzione, ma OWASP raccomanda di rifiutarlo a livello applicativo per evitare bypass di firma. Vettore di CVE storiche su jsonwebtoken, jose, ruby-jwt e altre librerie.
Alg confusion attack #
Vettore in cui il backend, configurato per RS256, accetta anche HS256 e usa la public key RSA come secret HMAC. L'attaccante che ha la pubkey (sempre, perché public) può forgiare token validi. Mitigation: vincolare l'algoritmo nella verifica (es. algorithms: ['RS256']).
HS256 #
HMAC-SHA256, signature simmetrica con secret condiviso fra issuer e verifier. Il secret deve essere casuale e di alta entropia (>= 256 bit, generato con openssl rand -base64 32) per resistere al brute force offline.
RS256 #
RSA-SHA256 con padding PKCS#1 v1.5, signature asimmetrica. Il backend ha la chiave privata per firmare, i client (o altri service) hanno solo la pubblica per verificare. Preferito a HS256 per architetture multi-service. Esiste anche RS384, RS512 con SHA-384/SHA-512.
ES256 / ES384 / ES512 #
ECDSA con curve P-256, P-384, P-521. Equivalente a RS256 ma con chiavi più corte (256 bit vs 2048-4096) e firme più veloci. Raccomandato per nuovi sistemi. Attenzione alla qualità del PRNG: ECDSA con randomness debole è catastrofico.
PS256 #
RSASSA-PSS-SHA256, RSA con padding PSS (probabilistic signature scheme). Variante moderna di RS256, raccomandata da NIST. Supportata dalle librerie JWT recenti, meno diffusa storicamente.
kid #
Key ID, header opzionale che identifica quale chiave usare per la verifica (utile in JWKS multi-key). Vulnerabilità note se non sanitizzato lato backend (path traversal con ../, SQL injection nella tabella keys).
jku / x5u #
jku (JWK Set URL): URL di un JWKS. x5u (X.509 URL): URL di un certificato X.509. Header che dichiarano dove trovare la chiave di verifica. Senza pinning lato backend, l'attaccante che controlla la URL controlla la chiave. Da ignorare salvo whitelist esplicita.
JWKS #
JSON Web Key Set (RFC 7517). Endpoint pubblico che pubblica le chiavi pubbliche di un identity provider in formato JSON. URL convenzionale: https://idp.example/.well-known/jwks.json. Cached con TTL ragionevole, refresh on rotation.
exp / nbf / iat #
Claim temporali RFC 7519. exp (expiration): timestamp Unix di scadenza, secondi. nbf (not before): timestamp prima del quale il token non è valido. iat (issued at): timestamp di emissione. Tutti in secondi (non millisecondi: errore comune di porting JS).
aud / iss / jti #
Claim semantici RFC 7519. aud (audience): identificatore del destinatario, mitigazione del confused deputy. iss (issuer): identificatore del provider che ha emesso il token, mitigazione del rogue IdP. jti (JWT ID): identificatore univoco, abilita anti-replay via blacklist server-side.
OWASP JWT Cheatsheet #
Documento OWASP che codifica le best practice di security per JWT: whitelist algoritmi, secret strength, claim mandatory, expiration, kid handling, jku/x5u pinning, refresh token rotation. Riferimento autoritativo per chi progetta o audita un'integrazione JWT.
FriendsOfPHP / SecLists #
SecLists (danielmiessler/SecLists su GitHub): collezione open source di wordlist per security testing. La sezione Passwords/scraped-JWT-secrets contiene secret JWT comuni raccolti da CTF, leak, codice pubblico. Sorgente del dataset di brute-force di questo tool insieme a wallarm/jwt-secrets.
WebCrypto API #
API standard del browser per primitive crittografiche (HMAC, RSA, ECDSA, AES, SHA). Definita in W3C Web Cryptography. Tutta la verifica HMAC e RSA del tool gira via crypto.subtle: nessuna libreria JS esterna, performance native, niente dati che lasciano la tab.

Domande frequenti sull'audit JWT

Sono il proprietario o il PM di un'API che usa JWT, non sono uno sviluppatore. Mi serve davvero questo tool?
Sì, ed è anzi uno dei target. Per ogni finding ricevi severity (critica, alta, media, bassa, informativa), descrizione del vettore in linguaggio operativo e link al CVE pubblico o alla raccomandazione OWASP. Se il report restituisce anche solo un finding critical, hai un argomento concreto da portare al team di sviluppo per chiedere come e quando l'integrazione verrà sistemata. Tipico segnale d'allarme: secret HS256 trovato nel dataset wallarm = secret fra i 10.000 più diffusi sul web = patch necessaria entro le 24 ore.
Dove cattomi un JWT della mia applicazione per testarlo?
Tre vie tipiche. (1) DevTools del browser: tab Network, filtra per le request all'API, cerca l'header Authorization: Bearer ..., copia tutto dopo "Bearer ". (2) Storage del client: spesso il JWT è in localStorage (key tipo access_token, idToken) o in cookie. (3) Sviluppatore: chiedi al team di prodottu un token di test (non di produzione su utente reale: meglio un account di staging). Il tool gira solo in locale, il token non lascia il browser, ma per igiene non incollare mai token reali in tool che non controlli.
Il tool decodifica anche la firma? Posso vederla?
Il terzo segmento (signature) viene mostrato come stringa base64url, non decodato. Le firme HMAC, RSA ed ECDSA sono byte raw e leggerle non aggiunge informazioni utili. Per verificarla serve la chiave: per HS256 usa il JWT decoder con secret nel campo dedicato; per RS256/ES256 puoi incollare la pubkey nel campo opzionale di questo audit, e se il token è HS256-spoofato con la pubkey come secret il check di alg confusion lo segnala.
Cosa succede se il tool trova un secret debole? Cosa significa praticamente?
Significa che chiunque conosca o indovini quel secret può forgiare token validi a piacere, impersonando qualunque utente. Pattern di mitigation immediata: (1) ruotare il secret a una stringa casuale crypto-safe (openssl rand -base64 32); (2) invalidare tutti i token in circolazione (forza re-login a tutti gli utenti, spiacevole ma necessario); (3) verificare i log applicativi delle ultime settimane per attività sospette su account privilegiati; (4) ripensare l'architettura: se HS256 è davvero la scelta giusta o se RS256 sarebbe più appropriato per l'arch.
Cos'è esattamente l'alg confusion attack? Il check è affidabile?
L'attacco sfrutta backend mal configurati che, ricevendo un token HS256, lo verificano con la stessa chiave usata per RS256, applicando l'algoritmo dichiarato nell'header del token (HS256) invece che quello atteso dall'architettura (RS256). Risultato: il backend tratta la public key RSA come secret HMAC, e siccome la public key è pubblica, l'attaccante può forgiare token validi. Il check del tool è affidabile al 100%: prende la pubkey che fornisci, la usa come secret HMAC contro la firma del token, se la verifica passa il vettore è confermato. Senza pubkey, il check viene saltato.
Audit profondo (10.000 secret) vs Audit normale (1.000): quando serve davvero?
Il tier fast (1.000 secret) copre il 95% dei casi reali: i secret comuni ("secret", "password", "changeme", combinazioni con il nome del progetto) sono tutti lì in cima. Il tier full (1.001-10.000) aggiunge la coda dei secret meno frequenti ma documentati in CTF, leak GitHub, pastebin storici. Quando usare il deep: (a) il fast non ha trovato match e vuoi escludere il vettore con coverage estesa prima di chiudere il triage; (b) audit di alto rigore prima di pubblicare un report ufficiale; (c) il backend è in scope NIS2 e devi documentare due diligence.
Token scaduto: è un finding bloccante?
No, è classificato INFO. Un token scaduto NON è una vulnerabilità di sicurezza (anzi, l'expiration è una mitigazione attiva). Il tool segnala lo stato per evitare false positive nel report (un audit che dicesse "manca exp" su token che invece ha exp ma è scaduto sarebbe un bug).
Lifetime > 30 giorni è realmente un problema?
Dipende dal use case. Per token di sessione utente: sì, 30 giorni è troppo, refresh token rotation con access token short-lived (15-60 min) è la pratica raccomandata. Per token di servizio (API key formato JWT): 30+ giorni può essere accettabile se ruotati e revocabili lato backend. Il tool segnala HIGH come default conservativo: valuta il context e ignora se il use case lo giustifica.
kid injection: come si exploita davvero?
Esempi reali di vettori. (1) kid: "../../../dev/null" -> il backend cerca la chiave nel filesystem -> trova file vuoto -> verifica HMAC con secret = stringa vuota -> forgery riuscita. (2) kid: "key1' UNION SELECT 'attacker'-- " -> il backend fa SQL su tabella keys -> SQLi -> chiave attacker controllata. Mitigation: trattare kid come input untrusted, whitelist alfanumerica, lookup esatto in mappa interna, mai parametro di query non parametrizzata.
Perché jku/x5u sono dichiarati ad alto rischio?
Permettono al token di dichiarare la URL della chiave pubblica con cui verificarsi. Se il backend la usa as-is (senza pinning a domini fidati), un attaccante che controlla la URL controlla la chiave -> firme valide a piacere. Mitigation: pinning whitelist di hostname autorizzati a livello backend, oppure ignorare jku/x5u e usare solo JWKS endpoint hardcoded.
Il tool integra una libreria PHP/JS esterna a runtime?
No. Parsing JWT (base64url + JSON.parse), brute-force HS256 (WebCrypto HMAC.verify), import della pubkey PEM (WebCrypto importKey con SubjectPublicKeyInfo): tutto API native del browser. Zero dipendenze, ~16 KB di JavaScript totali. Il dataset secrets è statico, ricompilato dal cron PHP server-side.
Differenza fra questo audit e il JWT decoder del sito?
Il JWT decoder è un visualizzatore: decodifica header e payload, spiega ogni claim, calcola il countdown a exp, opzionalmente verifica la firma HS256 se gli dai il secret. Questo audit assume la firma valida (o la verifica al volo per il check di alg confusion) e si concentra sui rischi di configurazione: vettori di forgery, weak secret, claim mancanti, header pericolosi. Sono complementari: decoder per capire cosa contiene un token, audit per capire se è esposto.
Privacy: il token che incollo viene salvato o tracciato?
No. Il tool gira interamente nel browser. Le uniche richieste di rete sono il GET dei file dataset secrets (identici per tutti gli utenti, completamente anonimi) e il GET dell'index.json. Il token incollato non viene mai inviato in alcuna richiesta, non viene salvato in localStorage, non viene tracciato in analytics. Verificabile aprendo il pannello Network di DevTools durante l'audit: zero richieste outgoing con i dati del token.
Posso fare audit di un Refresh Token o di un ID Token OpenID Connect?
Sì, sintatticamente sono entrambi JWT validi e l'audit funziona uguale. Punti rilevanti per refresh token: (a) exp deve essere ragionevolmente lungo (giorni-mesi tipico) ma con jti per anti-replay; (b) aud ristretto all'endpoint di refresh; (c) idealmente HS256 sostituito da RS256 in arch multi-service. Per ID token OIDC: iss deve matchare l'URL del provider OIDC, aud deve contenere il client_id, nonce deve matchare quello inviato nella authorization request.
Posso fare un audit completo del flusso, non del singolo token?
Questo audit segnala i rischi visibili dal singolo token. Per esaminare il flusso completo (rotazione delle chiavi, refresh token rotation, logout server-side, anti-replay con jti, audience binding, gestione di kid e jku/x5u in produzione, configurazione del provider OIDC) serve una review architetturale che attraversi codice, configurazione del provider e infrastruttura. Vai al CTA in fondo alla pagina.

L'autenticazione JWT della tua API regge un audit serio?

Questo tool segnala i rischi visibili dal singolo token: alg=none, weak secret, alg confusion, claim mancanti, header esoterici. Una review professionale esamina il flusso completo: configurazione del provider OIDC, rotazione delle chiavi (manuale o automatica), refresh token rotation con anti-replay via jti, logout server-side, audience binding, gestione di kid e jku/x5u in produzione, leeway sull'exp, hardening della libreria di verifica, exploitability assessment dei vettori OWASP sui codepath effettivamente raggiungibili. Se il triage di sopra ha mostrato un finding critical o high, il problema esiste già: il prossimo passo è capire impatto reale, costi e tempi della remediation. Lavoro su backend PHP, Laravel, Symfony, Node.js, Python con focus su API in produzione e adeguamenti normativi.

Review architettura JWT

Vuoi una stima realistica per il tuo progetto?

Wizard di 7 domande, 2 minuti, gratuito. Output: range di giorni-uomo, range di prezzo orientativo e raccomandazione di ingaggio. Tariffa di riferimento 300 euro al giorno. Pensato per progetti backend custom, integrazioni, audit di sicurezza o automazione AI.

Calcola il preventivo