Sfondo
Stiamo avviando un progetto per aggiungere un ulteriore fattore di autenticazione alla nostra applicazione web. Ciò comporta la creazione di un token TOTP (Time-Based One-Time Password) conforme a RFC 6238 ( link ). Questo token verrà consegnato all'utente tramite SMS o e-mail.
Sono consapevole che questo approccio non è ideale da un punto di vista della sicurezza (ad esempio Eurograbber, Sandroid, Emmental). Spero di guidare la nostra organizzazione per valutare altre opzioni, ma nel frattempo sto cercando le migliori pratiche per questo approccio.
Panoramica
- un utente esegue l'autenticazione alla nostra applicazione Web utilizzando il nome utente e la password
- l'utente avvia un'azione che attiva una valutazione del rischio
- se rischioso:
- estrae la chiave segreta crittografata dell'utente dal database (o genera una nuova chiave casuale se non è presente)
- usa la chiave segreta e la data / ora corrente per generare TOTP
- TOTP viene consegnato al numero di cellulare dell'utente tramite SMS (o consegnato via email)
- Visualizza la schermata di immissione TOTP
- L'utente riceve e inserisce TOTP
- Estrai la chiave segreta dal database e genera i TOTP
- convalidare TOTP fornito contro TOTP generato
- se valido, continua con l'azione originale
Domanda
C'è bisogno di una politica di scadenza per la chiave segreta dell'utente?
Logicamente la chiave segreta è ancora più sicura della password dell'utente (che non scade mai). Non lascia mai i nostri sistemi (l'application server e il database).
Potrei farlo scadere (e generarne uno nuovo) dire una volta al mese o una volta ogni 10 usi. Ma questo sembra davvero dare valore solo se il nostro database (e la chiave di crittografia) è stato compromesso (nel qual caso abbiamo problemi più grandi).
Ci sono delle buone pratiche qui?
Note / Presupposti
- La chiave segreta verrà generata utilizzando una classe SecureRandom di Java (con reseeding)
- La chiave segreta verrà crittografata quando memorizzata nel database
- Garantiremo il solo utilizzo di un token valido.
Un secondo tentativo di un token valido (all'interno della stessa finestra temporale) non sarà accettato. - La finestra temporale in cui il token è valido verrà mantenuta il più piccola possibile.
Ma deve essere abbastanza grande perché il token possa essere consegnato (sms / email) e che l'utente possa ricevere e inserire token.
Probabilmente inizieremo con 90 secondi e apporteremo le modifiche necessarie. - La finestra temporale ridotta dovrebbe prevenire gli attacchi di forza bruta?
Ma aggiungere un blocco utente dopo aver detto 10 tentativi di token non validi è probabilmente una buona idea. - Una volta che l'utente si è autenticato con un token valido, è valido per la durata della sua sessione. Non sarà più necessario per l'utente ripetere l'autenticazione più tardi.
Modifica Ri: Sebastion
Ho considerato il tuo approccio "KISS" alcune settimane fa, ma stavo programmando di seguire la rotta TOTP perché avrebbe fornito una maggiore flessibilità per il futuro. Se vogliamo utilizzare Google Authenticator (o partner con RSA, o Authy, ecc.), Siamo a metà strada. Semplifica anche il nostro sviluppo un po 'da quando la scadenza è incorporata nell'algoritmo.
Ma ... ora che faccio un passo indietro, penso che il tuo approccio sia probabilmente quello corretto. La sovra-progettazione e la complicazione eccessiva ora per un futuro che potrebbe non accadere mai è un odore di codice.
Una cosa che non ho menzionato sopra è che probabilmente userei qualcosa come 3 trenta secondi. Quindi, sul tuo ultimo punto, il tempo limite sarebbe di 90 secondi al massimo, o un minimo di 60 secondi, se il token è stato generato alla fine di una finestra.