Cosa succede se JWT viene rubato?


201

Sto cercando di implementare l'autenticazione senza stato con JWT per le mie API RESTful.

AFAIK, JWT è fondamentalmente una stringa crittografata passata come intestazioni HTTP durante una chiamata REST.

Ma cosa succede se c'è un intercettatore che vede la richiesta e ruba il token ? Quindi potrà fingere una richiesta con la mia identità?

In realtà, questa preoccupazione si applica a tutta l' autenticazione basata su token .

Come prevenirlo? Un canale sicuro come HTTPS?


1
Questo è il motivo per cui i token sono spesso validi solo per un breve periodo di tempo. E sì, dovresti usare HTTPS se sei preoccupato per la riservatezza dei tuoi dati.
Jonathon Reinhart,

4
@JonathonReinhart Ma se un token scade presto, il mio cliente dovrà ottenere un nuovo token eseguendo nuovamente l'autenticazione di volta in volta. Non è noioso?
smwikipedia,

@JonathonReinhart Penso di aver capito il motivo per cui il token ha vita breve. Perché in questo modo, il server non ha bisogno di tenere traccia della scadenza di un token e quindi lasciare spazio alla scalabilità. È una specie di trade-offtra having finer control of token expiratione having better scalability.
smwikipedia,

2
Questo può anche aiutare? - "Un meccanismo di sicurezza comune per rilevare il furto di token è tenere traccia delle origini dell'indirizzo IP della richiesta." - descritto in dettaglio nell'ultima sezione qui - firebase.google.com/docs/auth/admin/manage-sessions
Ula

3
Teoricamente, è impossibile prevenire il furto di token. Il meglio che possiamo fare è rilevare ciò che è successo e quindi revocare la sessione al più presto. Il metodo migliore per il rilevamento consiste nell'utilizzare i token di aggiornamento rotanti (come suggerito da RFC 6819). Ecco un blog che spiega questo in dettaglio: supertokens.io/blog/…
Rishabh Poddar

Risposte:


284

Sono l'autore di una libreria di nodi che gestisce l'autenticazione in modo abbastanza approfondito, express-stormpath , quindi inserirò alcune informazioni qui.

Prima di tutto, i JWT in genere NON sono crittografati. Mentre esiste un modo per crittografare i JWT (vedi: JWE ), questo non è molto comune nella pratica per molte ragioni.

Successivamente, qualsiasi forma di autenticazione (utilizzando o meno JWT) è soggetta agli attacchi MitM (man-in-the-middle). Questi attacchi si verificano quando un utente malintenzionato può VISUALIZZARE il traffico della TUA RETE mentre si effettuano richieste su Internet. Questo è ciò che il tuo ISP può vedere, l'NSA, ecc.

Questo è ciò che SSL aiuta a prevenire: crittografando il tuo traffico di RETE dal tuo computer -> alcuni server durante l'autenticazione, una terza parte che sta monitorando il tuo traffico di rete NON può vedere i tuoi token, password o cose del genere a meno che non siano in qualche modo in grado per ottenere una copia della chiave SSL privata del server (improbabile). Questo è il motivo per cui SSL è OBBLIGATORIO per tutte le forme di autenticazione.

Diciamo, tuttavia, che qualcuno è in grado di sfruttare il tuo SSL ed è in grado di visualizzare il tuo token: la risposta alla tua domanda è che , l'aggressore sarà in grado di utilizzare quel token per impersonare te e fare richieste al tuo server.

Ora è qui che entrano in vigore i protocolli.

I JWT sono solo uno standard per un token di autenticazione. Possono essere usati praticamente per qualsiasi cosa. Il motivo per cui i JWT sono in qualche modo interessanti è che puoi incorporare informazioni extra in essi e puoi confermare che nessuno ha incasinato (firma).

TUTTAVIA, i JWT stessi non hanno nulla a che fare con la "sicurezza". A tutti gli effetti, i JWT sono più o meno la stessa cosa delle chiavi API: solo stringhe casuali che usi per autenticarti su qualche server da qualche parte.

Ciò che rende la tua domanda più interessante è il protocollo utilizzato (molto probabilmente OAuth2).

Il modo in cui OAuth2 funziona è che è stato progettato per fornire ai client token TEMPORANEI (come i JWT!) Per l'autenticazione SOLO PER UN BREVE PERIODO DI TEMPO!

L'idea è che se il token viene rubato, l'attaccante può usarlo solo per un breve periodo di tempo.

Con OAuth2, devi autenticarti di nuovo con il server ogni tanto fornendo il tuo nome utente / password o le credenziali API e quindi ottenere un token in cambio.

Poiché questo processo si verifica di tanto in tanto, i token cambieranno frequentemente, rendendo più difficile per gli aggressori impersonare costantemente senza affrontare grossi problemi.

Speriamo che questo aiuti ^^


3
L'autore dell'articolo seguente sostiene che uno svantaggio di JWT è che l'unico modo per recuperare da un JWT rubato è generare una nuova coppia di chiavi e disconnettere efficacemente tutti gli utenti. Considerando che con gli ID di sessione memorizzati in un DB, il sito Web potrebbe eliminare solo le sessioni dell'utente interessato e disconnetterlo da tutti i dispositivi. Non sono sicuro di come OAuth2 si adatti all'immagine qui o se aiuti a mitigare gli svantaggi presentati. medium.com/@rahulgolwalkar/…
Marcel

4
L'autore non è corretto Esistono diversi modelli di progettazione che è possibile utilizzare per invalidare i token. Ma in generale: utilizzare un JWT per qualsiasi tipo di scopo di autenticazione è una cattiva idea. È molto più efficiente utilizzare un cookie di sessione con un'idea di sessione incorporata all'interno con firma crittografica.
rdegges il

1
@rdegges, per favore, dimmi come JWT sia una cattiva idea per l'autenticazione? e come posso utilizzare i cookie di sessione che hai citato nel tuo commento sopra?
noman tufail

6
È troppo lungo per digitare una singola risposta. Se vuoi saperne di più, ho tenuto un discorso dettagliato sull'argomento. Puoi vedere le mie diapositive online: speakerdeck.com/rdegges/jwts-suck-and-are-stupid
rdegges,

2
Teoricamente, è impossibile prevenire il furto di token. Il meglio che possiamo fare è rilevare ciò che è successo e quindi revocare la sessione al più presto. Il metodo migliore per il rilevamento consiste nell'utilizzare i token di aggiornamento rotanti (come suggerito da RFC 6819). Ecco un blog che spiega questo in dettaglio: supertokens.io/blog/…
Rishabh Poddar

31

So che questa è una vecchia domanda, ma penso di poter perdere i miei $ 0,50 qui, probabilmente qualcuno può migliorare o fornire un argomento per rifiutare totalmente il mio approccio. Sto usando JWT in un'API RESTful su HTTPS (ofc).

Affinché ciò funzioni, dovresti sempre emettere token di breve durata (dipende dalla maggior parte dei casi, nella mia app sto impostando il expreclamo su 30 minuti e ttlsu 3 giorni, quindi puoi aggiornare questo token finché ttlè ancora valido e il token non è stato inserito nella blacklist )

Per quanto riguarda authentication service, al fine di invalidare i token, mi piace usare un livello di cache in memoria ( redis nel mio caso) come JWT blacklist/ ban-listin primo piano, a seconda di alcuni criteri: (So che rompe la filosofia RESTful, ma i documenti memorizzati sono davvero di breve durata, come nella lista nera per il loro tempo di vita ttlrimanente - claim-)

Nota: i token nella lista nera non possono essere aggiornati automaticamente

  • Se user.passwordo user.emailè stato aggiornato (richiede la conferma della password), il servizio di autenticazione restituisce un token aggiornato e annulla (la lista nera) i precedenti, quindi se il tuo client rileva che l'identità dell'utente è stata in qualche modo compromessa, puoi chiedere a quell'utente di cambiare la sua password . Se non si desidera utilizzare la lista nera per essa, è possibile (ma non vi incoraggio a) convalidare il iatreclamo (emesso presso) rispetto al user.updated_atcampo (se jwt.iat < user.updated_atquindi JWT non è valido).
  • Utente disconnesso deliberatamente.

Alla fine convalidi il token normalmente come fanno tutti.

Nota 2: anziché utilizzare il token stesso (che è davvero lungo) come chiave della cache, suggerisco di generare e utilizzare un token UUID per il jtireclamo. Il che è buono e penso (non sono sicuro da quando mi è appena venuto in mente) che puoi usare lo stesso UUID anche del token CSRF, restituendo un secure/ non-http-onlycookie con esso e implementando correttamente l' X-XSRF-TOKENintestazione usando js. In questo modo si evita il lavoro di elaborazione della creazione di un altro token per i controlli CSRF.


9
Non è mai troppo tardi per contribuire con la tua idea. Grazie per la tua risposta.
smwikipedia,

2
Se memorizzi una lista nera sul server che deve essere controllata per ogni richiesta, perché non usare semplicemente la vecchia sessione?
Franklin Yu,

@FranklinYu Una lista nera è molto più "economica" di un archivio di sessioni complete. Poiché stai memorizzando oggetti valore-chiave di breve durata (a seconda del tempo di vita rimanente, che dovrebbe essere piuttosto breve) e ciò accade solo per le azioni di disconnessione e tali azioni che invalidano i token, quindi non tutti i token sono memorizzato ofc.
Frondor,

2
Quanto economico può essere? Prima di tutto, se si sta ancora archiviando qualcosa sul lato server, non si gode il vantaggio di "scalabilità" richiesto da JWT perché esiste ancora un server blacklist centrale con cui tutti i server delle applicazioni devono parlare prima di fare qualsiasi cosa. Se hai solo bisogno di archiviare 1k black list a causa della rapida scadenza, puoi fare lo stesso per le sessioni e quindi devi solo memorizzare 1k sessioni.
Franklin Yu,

3
Mi piace questo approccio. In realtà non è necessario controllare la lista nera su ogni richiesta, solo su una richiesta che si verifica dopo la scadenza del JWT (che è possibile leggere dal token stesso) e fino al periodo TTL successivo. In un caso d'uso "standard", ciò dovrebbe accadere, al massimo, una volta nella vita di un determinato token. Una volta aggiornato, puoi probabilmente rifiutare eventuali richieste di aggiornamento future. Grazie @Frondor
John Ackerman il

7

Mi dispiace essere un po 'in ritardo su questo, ma avevo le stesse preoccupazioni e ora voglio contribuire con qualcosa sullo stesso.

1) rdegges ha aggiunto un punto eccellente, che JWT non ha nulla a che fare con la "sicurezza" e semplicemente convalida, se qualcuno ha incasinato il payload o meno (firma); ssl aiuta a prevenire le violazioni.

2) Ora, se ssl è anche in qualche modo compromesso, qualsiasi intercettatore può rubare il nostro token al portatore (JWT) e impersonare l'utente reale, un passo di livello successivo che cosa si può fare è cercare la "prova di possesso" di JWT dal cliente .

3) Ora, con questo approccio, il presentatore del JWT possiede una particolare chiave Proof-Of-Possession (POP), che il destinatario può confermare crittograficamente se la richiesta proviene dallo stesso utente autentico o meno.

Ho fatto riferimento a questo articolo Proof of Possesion e sono convinto con l'apporach.

Sarò felice, se in grado di contribuire con qualsiasi cosa.

Saluti (y)


0

Non possiamo semplicemente aggiungere l'ip dell'host iniziale che ha richiesto di generare questo token JWT come parte del reclamo? Ora quando il JWT viene rubato e utilizzato da una macchina diversa, quando il server convalida questo token, potremmo verificare se l'ip della macchina richiesta corrisponde a quello impostato come parte del reclamo. Ciò non corrisponderebbe e quindi il token può essere rifiutato. Inoltre, se l'utente tenta di manipolare il token impostando il proprio ip sul token, il token verrà rifiutato quando il token viene modificato.


Questa è una possibile soluzione, ma per i client dietro un firewall è tipico che un indirizzo IP venga scelto da un pool di indirizzi e che può cambiare in qualsiasi momento.
SpeedOfSpin
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.