Ho bisogno di un “salt random” una volta per password o solo una volta per database?

Oltre alla mia precedente domanda sulle password salate in PHP / MySQL , ho un’altra domanda riguardante i sali.

Quando qualcuno dice “usa un salt random” per aggiungere / aggiungere una password, questo significa:

  • Creare una statica una stringa di caratteri generata in modo casuale da 1 volta , oppure
  • Creare una stringa di caratteri che cambia casualmente ogni volta che viene creata una password ?

Se il sale è casuale per ogni utente e memorizzato insieme alla password con hash, come viene recuperato il sale originale per la verifica?

Un nuovo sale dovrebbe essere generato casualmente per ogni utente e ogni volta che cambiano la loro password come minimo. Ad esempio, non basarsi solo su un sito ampio, in quanto ciò sconfigge il punto di utilizzo di un sale in primo luogo.

L’utilizzo di un sale unico per ogni utente è tale che se due utenti hanno la stessa password non otterranno lo stesso hash risultante. Significa anche che un attacco di forza bruta dovrebbe essere montato su ciascun utente individualmente piuttosto che essere in grado di pre-calcolare una tabella arcobaleno per il sito.

Quindi si memorizza il risultato hash(salt + password) il sale e la password hash(salt + password) del database hash(salt + password) , insieme al salt per ogni utente. È ansible memorizzarli in colonne separate o tutti in una colonna (separati da un carattere non utilizzato negli hash, quindi ; ad esempio). Finché puoi recuperare entrambi, starai bene.

Tuttavia, se il tuo database è compromesso, a causa di qualcuno che ottiene l’accesso locale o tramite attacchi SQL injection, allora saranno disponibili sia l’hash salt che l’hash finale, il che significa che un attacco di forza bruta sulle password degli utenti sarebbe banale. Per combatterlo, come suggerito da The Rook , puoi anche usare una chiave segreta in tutto il sito memorizzata in un file localmente come un altro input del tuo metodo di hashing in modo che anche un utente malintenzionato debba saperlo per montare un attacco efficace. Il che significa che il tuo DB dovrebbe essere compromesso E l’attaccante avrebbe bisogno di accedere ai file locali. Quindi usando hash(hash(salt + secret) + password) , ecc.

Mentre nella maggior parte degli algoritmi miri a rendere le cose il più veloci ansible, per l’hashing della password che desideri rallentare, questo è chiamato Key Strengthening (o talvolta Key Stretching). Se ci vogliono 0.00001 secondi per il ritorno della funzione hash, qualcuno può provare a forzare brute forzando 100.000 password al secondo fino a quando non trovano una corrispondenza. Se impiega 1 secondo per la tua funzione hash per sputare il risultato, non è un grosso problema per quanto riguarda l’accesso di qualcuno alla tua applicazione, ma per craccare la password è un grosso problema dato che ogni tentativo impiegherà 1 secondo per ottenere un risultato, il che significa che ci vorrebbero 100.000 volte il tempo per testare ogni password forzata bruta di quella che userebbe la tua funzione di hash originale.

Per rendere più lenta la tua funzione di hash, devi solo eseguirla più volte. Ad esempio, potresti fare new_hash = salt + password + previous_hash 100.000 volte. Potrebbe essere necessario regolare il numero di iterazioni su un valore superiore se è troppo veloce. Se si desidera poter modificare il valore in un secondo momento, accertarsi di memorizzare il numero di iterazioni con il record utente in modo da non influire sulle password memorizzate in precedenza.

Il tuo record utente dovrebbe ora avere un campo formattato come ” $$$$ ” (o come campi separati se lo desideri).

Quando l’utente immette la propria password, è ansible recuperare il sale e il numero di iterazioni dal DB e il segreto del sitewide da un file locale e verificare che quando si esegue lo stesso numero di iterazioni con sale e password, l’hash risultante corrisponda a ciò hai memorizzato

Se l’utente cambia la sua password, allora dovresti generare un nuovo salt.

Il metodo di hashing che usi non ha importanza (ma l’algoritmo di hashing fa *). Sopra ho suggerito l’ hash(hash(salt + secret) + password) ma ugualmente potrebbe essere hash(hash(salt) + hash(secret) + hash(password)) . Il metodo che utilizzi non modifica l’efficacia della memorizzazione della password, non è più sicuro dell’altro. Affidarsi alla progettazione di come si hash la password e salare insieme per fornire sicurezza si chiama sicurezza attraverso l’oscurità e dovrebbe essere evitato.

* Non dovresti usare MD5 o SHA-1 poiché sono considerati insicuri. Utilizzare invece la famiglia SHA-2 (SHA256, SHA512, ecc.). ( Rif. )

La seconda alternativa è quella corretta.

Tradizionalmente, il sale viene memorizzato insieme alla password con hash, ma non crittografato (tipicamente pre-installato, ad esempio nelle password unix )

Aggiornamento: il metodo utilizzato nella maggior parte dei nuovi sistemi Unix è questo .

Il sale deve essere conservato con l’hash per consentire la verifica. La migliore pratica sarebbe quella di utilizzare un sale diverso ogni volta che viene creata o modificata una password.

Cambiare il sale in modo dinamico è molto più sicuro che avere un sale statico.

Rendi unici i sali per utente e non un sale globale. Modificali ogni volta che un utente effettua l’accesso, ad esempio.

Concatenando il sale alla fine della password, l’hashing è OK, ma è una formula facilmente ipotizzabile. Meglio venire con il tuo, cioè tessere il sale e la password per creare una nuova stringa, quindi hash, dato che md5 (password + sale) è ancora vulnerabile all’attacco del dizionario.