2010-05-03 13 views
6

Il flusso normale per la reimpostazione della password di un utente per posta è questa:Ristabilimento di password per e-mail, senza una tabella del database

  1. generare una stringa casuale e conservarla in una tabella di database
  2. stringa di e-mail a utenti
  3. L'utente fa clic sul collegamento contenente la stringa
  4. La stringa è convalidata rispetto al database; se corrisponde, l'utente pw viene resettato

Tuttavia, mantenere un tavolo e scadere di vecchie stringhe ecc sembra un po 'inutile. Ci sono evidenti difetti in questo approccio alternativo?

  1. generare un hash MD5 della password esistente dell'utente
  2. stringa Email hash per utente
  3. utente fa clic sul link contenente stringa
  4. String è convalidato dal hashing ancora esistenti pw; se corrisponde, l'utente pw viene resettato

Si noti che la password dell'utente è già memorizzata in un formato hash e salato e sto ancora eseguendo l'hashing per ottenere una stringa unica ma ripetibile.

E sì, c'è un "difetto" ovvio: il link di reset così generato non scadrà finché l'utente non cambia la sua password (fa clic sul collegamento). Non vedo davvero perché questo sarebbe un problema - se la casella di posta è compromessa, l'utente è fregato comunque. E non c'è alcun rischio di riutilizzo, dal momento che una volta modificata la password dell'utente, il link di reset non corrisponderà più.

+1

+1 per l'idea interessante –

risposta

8

Per rimediare allo obvious flaw, aggiungi la data corrente (e più informazioni relative al tempo che rappresentano la frazione corrente di un giorno se anche un giorno è troppo lungo) a ciò che stai facendo per generare la stringa misteriosa e controllarla - questo fa sì che la stringa "scadano" (puoi controllare la data precedente o la data o la frazione corrente se vuoi "scadere" più a lungo). Quindi mi sembra che il tuo schema sia abbastanza fattibile.

+0

Ah, mi hai battuto;). Assicurati di utilizzare i dati a seconda degli utenti. Fuso orario :) –

+0

Come si ottiene la data di scadenza dall'hash dell'utente inviato per verificare se la data corrente è passata? Dovrebbe essere criptato e attaccato. Altrimenti: A) L'hai appena codificato, l'utente interrompe la codifica, vanifica lo scopo di avere anche un controllo del tempo. B) Lo lasci come testo in chiaro, stessa cosa. Poi di nuovo se hai qualche S segreto globale per evitare sprechi di spazio, potresti mandare l'utente 'HASH (S || time || userpass)', 'time'; L'utente restituisce 'hash',' time', che consentirebbe al server di testare 'HASH (S || time_user_sent_back || userpass)' contro l'hash che l'utente ha restituito. –

+2

@Longpoke, se (ad esempio) la stringa deve essere valida per '2010/05/06' e' 2010/05/07', si aggiunge '2010/05/06' alla stringa che si sta tagliando - questo è tutto. Al momento del controllo, controlli gli hash che ottieni aggiungendo i formati ISO di oggi e di ieri - è praticamente impossibile. Se desideri una granularità migliore di un giorno per la scadenza della stringa speciale, utilizza anche la _frazione appropriata di un giorno_ - ad es. se vuoi che la stringa duri circa 1,5 giorni, usa "mezza giornata" (ad esempio AM o PM) tra ciò che stai facendo (e controlla 3 possibilità) - anche non difficile! –

3

Se qualcuno ha eseguito l'accesso al database con gli hash delle password, non conoscono le password effettive. Se si implementa questo sistema, possono generare i link di ripristino e reimpostare le password. Con stringhe casuali e conoscenza di un compromesso, è possibile invalidare tutte le stringhe casuali e solo gli utenti nel processo di reimpostazione della password potrebbero essere compromessi anche senza la conoscenza dell'accesso. Non è uno scenario probabile, ma potrebbe valerne la pena considerando il sovraccarico nominale delle stringhe casuali.

+0

Una volta che il sito è stato compromesso, si desidera reimpostare anche tutte le password, poiché l'utente malintenzionato potrebbe averle registrate in testo non crittografato mentre sono inviate al server (un caso non evitabile, solo i certificati client SSL possono fermarlo). Per non parlare dell'hacker che probabilmente ha rotto un buon 90% delle password con hash in poche ore. Inoltre, se si utilizza il consiglio di Alex Martelli, è possibile aggiungere un ulteriore controllo sulla richiesta di ripristino rispetto al tempo di compromissione, che è effettivamente uguale a quello che hai appena suggerito :) –

+0

Tranne che non ogni utente avrà una stringa casuale ma ogni utente ha effettivamente una stringa generata, quindi se non sei immediatamente consapevole del compromesso, solo alcuni utenti ne sono comunque interessati. Oltre al 90% con password deboli, ovviamente. – drawnonward

+0

Gah! Questa è sicuramente una vera vulnerabilità, anche se, come dice Longpoke, una volta che l'attaccante entra nel DB tutte le scommesse sono state cancellate: non hanno bisogno di futz con i link di reset, possono semplicemente cambiare le password direttamente nella tabella utente. +1 per trovarlo però! – jpatokal

2

In realtà dopo aver ripensato a questo, il tuo metodo è potenzialmente meno sicuro di "Il flusso normale".

Se hai appena rispedite HASH(HASH(user's original password)), posso vedere gli scenari in cui questo può dare una leva attaccante:

Scenario 1:

  1. Jim registri sul tuo sito come [email protected].
  2. Jim richiede una reimpostazione della password, ma non la utilizza. L'email di reset viene lasciata nella sua casella di posta per l'eternità.
  3. Jim cambia il suo indirizzo email sul tuo sito.
  4. [email protected] compromesso da Bob.
  5. Bob ora esegue un attacco bruteforce tramite la sua farm distribuita GPGPU e recupera la password di Jim.

Scenario 2:

  1. Jim utilizza una password jimjonesupinthisma! per il suo conto bancario.
  2. Jim registri sul tuo sito come [email protected]. [email protected] è non in alcun modo associato al conto bancario Jim s.
  3. [email protected] compromesso da Bob.
  4. Bob ora richiede un reset, ora ha HASH(HASH(jim's password)).
  5. Bob ora esegue un attacco bruteforce tramite la sua farm distribuita GPGPU e recupera la password Jim, che quindi utilizza per accedere al conto bancario Jim s.

Scenario 3:

(Il tuo sito utilizza TLS, gli utenti registrarsi tramite TLS.)

  1. Jim registri sul tuo sito come [email protected].
  2. Bob richiede una reimpostazione della password sull'account Jim s.
  3. Bob funziona per NSA a Room 641A.
  4. Bob utilizza il suo sniffer Internet globale e ottiene HASH(HASH(jim's password)) come viene inviato via email a [email protected].
  5. Bob ora esegue un attacco bruteforce tramite la sua farm distribuita GPGPU e recupera la password di Jim.

Varianti di scenari 1 e 2 accadere tutto il tempo (a seconda di quanto sia forte l'hash e la password sono), io non sono così sicuro circa 3. Il punto è, il tuo metodo di porri informazioni non necessarie, che possono effettivamente sfruttare un utente malintenzionato contro il tuo utente.

Suggerisco di utilizzare token generati in modo casuale che hanno nulla da fare con la password dell'utente.

+0

Scusate, qui non sono d'accordo: tutti i vostri scenari sembrano presupporre che la stringa doppiamente salata e con hash è di qualche utilità nel recuperare la stringa originale, ma questo non sembra essere il caso. MD5 è noto per essere vulnerabile agli attacchi di collisione, ma il tuo ipotetico hacker avrebbe bisogno di un attacco preimage con successo per ottenere la password dall'hash. Il miglior attacco del genere noto fino ad oggi contro un singolo round di MD5 non salato ha una complessità di 2^123, e anche il cracking è saldamente nel regno della fantascienza. – jpatokal

+0

Non è necessario (e di solito non si vuole) una collisione, solo una password (tramite dizionario e quindi fallback a bruteforce di un set di caratteri attraverso cifre da 1-n). La maggior parte degli utenti ha password deboli e nessun hash li salverà davvero. Questi attacchi sono _real_, anche se non così comuni come il tipico attacco di script kiddie di cui si sente parlare. In realtà, ha più a che fare con la determinazione ed essere nel posto giusto al momento giusto. –

+0

Questi attacchi sono reali contro MD5 non salato, in cui è possibile utilizzare una tabella arcobaleno per invertire gli hash, ma le password qui sono salate e double-hash. – jpatokal

0

diciamo che in un caso molto raro, due dei vostri utenti avevano la stessa password con hash anche dopo aver concatenato salt saltato su di esso; ci sarebbe un problema, giusto? Immagino che non ti farebbe male se aggiungessi un'email o Hashid di user_id al link per la reimpostazione della password.

0

Proprio passati da questo problema e avere un'idea:

1) Emettere un JWT (JSON Web Token) con informazioni su account utente.Il token ha una scadenza, diciamo 1 ora.

2) Inviare il token per l'utente in una e-mail/link

3) L'utente fa clic sul collegamento, il token viene inviato al server di endpoint, il token viene convalidato. Se valido, spacchetta il token e aggiorna l'account utente

Eventuali difetti in questo approccio? Nessun database viene toccato (tranne che per le nuove password utente se necessario)

+0

Sì, è possibile utilizzare il token più volte, ma I * m ok con quello. È una buona cosa. Ho impostato la scadenza del token a 1 ora, quindi l'uso improprio è molto improbabile. Cosa mi manca? È così semplice e funziona magnificamente, che devo aver perso qualcosa. – Spock

+0

Inoltre, inserisco l'indirizzo IP della richiesta nel token. Quindi, durante la convalida, abbinare l'IP del chiamante. Il token può quindi essere utilizzato solo dallo stesso dispositivo che ha avviato la richiesta. Questa è solo una misura extra. Gli spoofers IP avrebbero comunque bisogno del token e entro 1 ora. – Spock