In un'implementazione TOTP, deve esserci una politica di scadenza per la chiave segreta dell'utente?

4

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.

    
posta matt1616 29.03.2016 - 18:56
fonte

1 risposta

4

Direi: non dovresti avere una chiave segreta. Dato che intendi inviare SMS o inviare tramite e-mail questi token, significa che non è necessario alcun codice segreto.

Invece, suggerirei semplicemente un token casuale, salvarlo nel database con un tempo di scadenza (ad esempio 90 secondi da ora) e poi inviarlo. Ogni tentativo di entrare nel token deve invalidare il token e chiedere all'utente l'opportunità di inviare un nuovo token, quindi ogni token è sempre "1 tentativo, con o senza successo". Aggiungi anche un Captcha per impedire a qualcuno di lanciare un attacco casuale nella speranza di "colpire il codice giusto la prima volta solo per fortuna".

Non è assolutamente necessario utilizzare il protocollo TOTP se non si intende permettere all'utente di salvare il seme nel proprio dispositivo e quindi generare codici "offline".

Se tuttavia permetti all'utente di salvare i propri seed "offline", ad esempio per eseguire il provisioning di Google Authenticator, allora può essere una buona idea, ma a volte non è una pratica del settore, per riprovare il token.

Se continuerai a utilizzare un "seme" o una "chiave segreta", ti suggerirei di utilizzare HOTP, ad esempio codici basati sugli eventi. Perché con TOTP avrai il problema di inviare a volte token già scaduti, perché TOTP funziona come un orologio che "scandisce" ogni X secondi, nel tuo caso, 90 secondi. Se l'orologio indica "85 secondi" e lo invii, sarà già scaduto quando arriverà all'utente, aggiungendo costi inutili e aggiungendo frustrazione all'utente.

    
risposta data 30.03.2016 - 07:03
fonte

Leggi altre domande sui tag