Pagina protetta da password dimenticata: un'implementazione stateless server è valida?

8

Questa è un'altra domanda "Come è stata dimenticata la mia password?". Tuttavia, affronta esplicitamente due opzioni di implementazione che ho incontrato di recente.

Gli approcci comuni [1,2] che conosco sono basati su un token casuale che può essere utilizzato solo una volta e che ha una validità limitata:

  • Visite degli utenti nella pagina delle password dimenticate
  • L'utente fornisce l'indirizzo email (o simile)
  • Se l'email è associata a un account utente valido
    • L'app genera un token unico e casuale t. t è di sufficiente entropia (diciamo 128 bit).
    • L'app memorizza il token casuale t e il timestamp creato con l'utente nel database
    • L'app invia un'email contenente un link per la reimpostazione della password all'indirizzo email dell'utente. Il link ha un aspetto simile al seguente: link
  • L'utente fa clic sul link nell'email
  • L'app controlla
    • se c'è un token all'interno del database per un dato utente
    • se sì, verifica che sia ancora valido in base al timestamp memorizzato
    • se sì, consente all'utente di accedere alla pagina resetPassword
  • L'utente imposta una nuova password
  • Successivamente, l'app invalida il token t

Puoi aggiungere un po 'più di sicurezza come canali fuori banda o domande di sicurezza. Ma per me, questa è la migliore pratica comune di cui sono a conoscenza.

Ora considera un approccio diverso. Perderemo la proprietà monouso. Tuttavia, il vantaggio è che l'app non deve tenere traccia degli stati dei token.

Invece di generare un token casuale, useremo un HMAC come segue:

  • token = HMAC_k (email, timestamp)

k è un segreto che l'app conosce sufficiente entropia. Il link di reset che viene inviato via email all'utente appare come segue:

Quando l'utente accede al collegamento, l'app lo verifica come segue:

  • calcola HMAC in base ai parametri URL: token_calculated = HMAC_k (email, timestamp)
  • controlla se il token fornito come parametro URL e la corrispondenza HMAC calcolata
  • se sì, controlla se il token è ancora valido in base al timestamp
  • se sì, consenti all'utente di accedere alla pagina resetPassword

A mio parere, la proprietà di non dover mantenere uno stato lato server è più preziosa della proprietà monouso. Ciò presuppone che una validità ragionevole e breve di token sia configurata sul lato server, ad esempio da 20 a 30 minuti.

Mi piacerebbe davvero sapere cosa pensano gli altri del secondo approccio. Soprattutto, se ci sono degli svantaggi che non avrei ancora notato.

[1] link

[2] link

    
posta user32387 17.02.2015 - 10:57
fonte

2 risposte

7

La tua domanda è ben scritta e tu capisci bene i problemi. Non c'è niente di fondamentalmente sbagliato con l'approccio token crittografico che descrivi. Alcune cose di cui essere a conoscenza:

  • La maggior parte dei siti in questi giorni richiede un uso intensivo del database, quindi l'archiviazione di un token di reimpostazione della password è un piccolo sovraccarico.
  • Dovresti limitare il numero di email di reimpostazione della password che possono essere generate (ad esempio, massimo di 2 per 30 minuti, per ciascun indirizzo di posta elettronica), che richiede la scrittura nel database.
  • Sei dipendente da K rimanendo segreto; questo potrebbe essere copiato da un amministratore malintenzionato (o forzato bruto, se debole) - mentre i token del database evitano questo singolo punto di errore.
  • Una debolezza comune (sebbene minore) con schemi di reimpostazione della password è la perdita del token verso siti esterni nell'intestazione del referer. Avere il token è strettamente monouso può aiutare con questo - anche se è possibile risolvere questo problema con i token criptati pure.

C'è una scelta simile con la generazione di cookie di sessione - utilizzando la crittografia o il database. In effetti, le considerazioni sulle prestazioni sono molto più significative per i cookie di sessione, poiché questo lavoro viene eseguito per ogni richiesta. Nonostante il sovraccarico, la maggior parte dei siti utilizza token di database, per i minori vantaggi di sicurezza.

    
risposta data 17.02.2015 - 11:32
fonte
1

Non è necessario perdere la proprietà una tantum. Immagina che il token di reimpostazione della password sia (concettualmente, aggiungi dettagli): HMAC (email, timestamp, current_password_hash) , dove l'hash della password corrente è l'hash che hai archiviato nel tuo database (si spera basato su alcuni KDF) e questa è la password che l'utente non conosce.

Quando l'utente cambia password, il valore di questo hash sarà diverso e quindi il token non sarà più valido. Anche se l'utente imposta la stessa password (anche se improbabile, come avrebbero dovuto provarlo), una corretta implementazione dell'hash della password dovrebbe includere un nonce e l'hash della password sarà diverso dopo il reset, anche se la password è la stessa. Questo fondamentalmente sta sfruttando il fatto che hai già memorizzato alcuni stati nel database (l'hash della password) e puoi saltare la memorizzazione di un altro.

P.S. k dovrebbe davvero rimanere segreto - questa è una delle maggiori preoccupazioni:)

    
risposta data 04.05.2017 - 15:39
fonte

Leggi altre domande sui tag