php $2 - Sicuro hash e sale per le password di PHP




7 Answers

DISCLAIMER : questa risposta è stata scritta nel 2008.

Da allora, PHP ci ha fornito php.net/manual/en/function.password-hash.php e password_verify e, dal momento della loro introduzione, sono il metodo consigliato per l'hashing e il controllo delle password.

La teoria della risposta è comunque una buona lettura.

TL; DR

cosa non fare

  • Non limitare i caratteri che gli utenti possono immettere per le password. Solo gli idioti fanno questo.
  • Non limitare la lunghezza di una password. Se i tuoi utenti vogliono una frase con supercalifragilisticexpialidocious in essa, non impedirgli di usarla.
  • Non memorizzare mai la password dell'utente in testo normale.
  • Non inviare mai una password al tuo utente, tranne quando hanno perso la loro e ne hai inviato una temporanea.
  • Mai, mai registrare le password in alcun modo.
  • Mai parole d'ordine hash con SHA1 o MD5 o persino SHA256! I cracker moderni possono superare i 60 e 180 miliardi di hash / secondo (rispettivamente).
  • Non mischiare bcrypt e con l'output raw di hash () , usa l'output hex o base64_encode. (Questo vale per qualsiasi input che può avere un ladro \0 in esso, che può seriamente indebolire la sicurezza.)

dos

  • Usa scrypt quando puoi; bcrypt se non puoi.
  • Usa PBKDF2 se non puoi usare bcrypt o scrypt, con gli hash SHA2.
  • Ripristina le password di tutti quando il database è compromesso.
  • Implementare una lunghezza minima ragionevole di 8-10 caratteri, oltre a richiedere almeno 1 lettera maiuscola, 1 lettera minuscola, un numero e un simbolo. Ciò migliorerà l'entropia della password, rendendola più difficile da decifrare. (Vedere la sezione "Che cosa rende una buona password?" Per qualche discussione.)

Perché le password hash comunque?

L'obiettivo delle password di hashing è semplice: impedire l'accesso malevolo agli account utente compromettendo il database. Quindi l'obiettivo dell'hash delle password è quello di scoraggiare un hacker o un cracker costando loro troppo tempo o denaro per calcolare le password in testo semplice. E tempo / costo sono i migliori deterrenti nel tuo arsenale.

Un altro motivo per cui si desidera un buon hash robusto su un account utente è quello di darti il ​​tempo sufficiente per cambiare tutte le password nel sistema. Se il tuo database è compromesso, avrai bisogno di tempo sufficiente per bloccare almeno il sistema, se non cambierai ogni password nel database.

Jeremiah Grossman, CTO di Whitehat Security, ha dichiarato sul suo blog dopo un recente recupero della password che ha richiesto la violazione della sua protezione con password brute-force:

È interessante notare che, vivendo questo incubo, ho imparato MOLTO che non sapevo di password cracking, archiviazione e complessità. Sono giunto ad apprezzare il motivo per cui la memorizzazione delle password è sempre più importante della complessità della password. Se non sai come viene archiviata la tua password, tutto ciò che puoi davvero dipendere è la complessità. Questo potrebbe essere una conoscenza comune per i professionisti di password e crittografia, ma per l'esperto medio di InfoSec o Web Security, ne dubito fortemente.

(Enfasi mia.)

Ciò che rende comunque una buona password?

Entropy . (Non che io sottoscrivo pienamente il punto di vista di Randall).

In breve, l'entropia è la quantità di variazione all'interno della password. Quando una password è solo lettere minuscole in caratteri latini, è solo 26 caratteri. Questa non è una grande variazione. Le password alfanumeriche sono migliori, con 36 caratteri. Ma consentire maiuscole e minuscole, con simboli, è di circa 96 caratteri. È molto meglio delle semplici lettere. Un problema è che, per rendere memorabili le nostre password, inseriamo schemi che riducono l'entropia. Oops!

L'entropia della password è facilmente approximated . L'utilizzo dell'intera gamma di caratteri ascii (circa 96 caratteri tipizzabili) produce un'entropia di 6,6 per carattere, che a 8 caratteri per una password è ancora troppo bassa (52,679 bit di entropia) per la sicurezza futura. Ma la buona notizia è che password più lunghe e password con caratteri unicode aumentano davvero l'entropia di una password e rendono più difficile il crack.

C'è una discussione più lunga sull'entropia della password sul sito Crypto StackExchange . Una buona ricerca su Google mostrerà anche molti risultati.

Nei commenti ho parlato con @popnoodles, che ha sottolineato che l' applicazione di una password di X con X molte lettere, numeri, simboli, ecc, può effettivamente ridurre l'entropia rendendo lo schema delle password più prevedibile. Sono daccordo. La casualità, nel modo più casuale possibile, è sempre la soluzione più sicura, ma meno memorabile.

Per quanto ne so, la migliore password del mondo è Catch-22. O il suo non memorabile, troppo prevedibile, troppo breve, troppi caratteri unicode (difficile da scrivere su un dispositivo Windows / Mobile), troppo lungo, ecc. Nessuna password è veramente sufficiente per i nostri scopi, quindi dobbiamo proteggerli come se fossero erano a Fort Knox.

Migliori pratiche

Bcrypt e scrypt sono le migliori pratiche attuali. scrypt sarà migliore di bcrypt in tempo, ma non ha visto l'adozione come standard da parte di Linux / Unix o dai server web e non ha ancora avuto recensioni approfondite dell'algoritmo pubblicato. Ma ancora, il futuro dell'algoritmo sembra promettente. Se stai lavorando con Ruby, c'è una gemma che ti aiuterà e Node.js ora ha il suo pacchetto scrypt . È possibile utilizzare Scrypt in PHP tramite l'estensione Scrypt o l'estensione Libsodium (entrambi sono disponibili in PECL).

Consiglio vivamente di leggere la documentazione per la funzione crypt se vuoi capire come usare bcrypt, o openwall.com/phpass un good wrapper o usare qualcosa come openwall.com/phpass per openwall.com/phpass più legacy. Raccomando un minimo di 12 round di bcrypt, se non da 15 a 18.

Ho cambiato idea sull'uso di bcrypt quando ho appreso che bcrypt utilizza solo il programma chiave di blowfish, con un meccanismo a costo variabile. Quest'ultimo consente di aumentare il costo per forzare una password aumentando la programmazione delle chiavi già costose di blowfish.

Pratiche medie

Non riesco quasi più a immaginare questa situazione. openwall.com/phpass supporta PHP da 3.0.18 a 5.3, quindi è utilizzabile su quasi tutte le installazioni immaginabili e dovrebbe essere usato se non si è certi che il proprio ambiente supporti bcrypt.

Supponiamo però che non sia possibile utilizzare bcrypt o PHPASS. Cosa poi?

Prova un'implementazione di PDKBF2 con il numero massimo di round che il tuo ambiente / applicazione / percezione dell'utente può tollerare. Il numero più basso che raccomanderei è di 2500 colpi. Inoltre, assicurati di usare hash_hmac() se è disponibile per rendere l'operazione più difficile da riprodurre.

Pratiche future

Venire in PHP 5.5 è una libreria completa di protezione con password che astrae qualsiasi difficoltà a lavorare con bcrypt. Mentre molti di noi sono bloccati con PHP 5.2 e 5.3 negli ambienti più comuni, in particolare gli host condivisi, @ircmaxell ha creato un livello di compatibilità per la prossima API compatibile con le versioni precedenti di PHP 5.3.7.

Ricapitolazione e disclaimer della crittografia

La potenza computazionale necessaria per rompere effettivamente una password con hash non esiste. L'unico modo per i computer di "crackare" una password è di ricrearlo e simulare l'algoritmo di hash utilizzato per proteggerlo. La velocità dell'hash è correlata linearmente alla sua capacità di essere forzata bruta. Peggio ancora, la maggior parte degli algoritmi di hash può essere facilmente parallelizzata per eseguire ancora più velocemente. Questo è il motivo per cui costosi schemi come bcrypt e scrypt sono così importanti.

Non è possibile prevedere tutte le minacce o le vie di attacco, quindi è necessario fare il possibile per proteggere i propri utenti. Se non lo fai, potresti anche perdere il fatto che sei stato attaccato fino a quando non è troppo tardi ... e sei responsabile . Per evitare quella situazione, agisci paranoico per cominciare. Attaccare il proprio software (internamente) e tentare di rubare le credenziali dell'utente, modificare gli account di altri utenti o accedere ai propri dati. Se non collaudi la sicurezza del tuo sistema, allora non puoi incolpare nessuno tranne te stesso.

Infine: non sono un crittografo. Qualunque cosa abbia detto è la mia opinione, ma penso che sia basata sul buon vecchio buon senso ... e su molte letture. Ricorda, essere il più paranoico possibile, rendere le cose difficili da intromettere il più possibile, e poi, se sei ancora preoccupato, contatta un hacker o un crittografo con cappello bianco per vedere cosa dicono del tuo codice / sistema.

bcrypt sha

Attualmente è stato detto che MD5 è parzialmente insicuro. Tenendo conto di ciò, mi piacerebbe sapere quale meccanismo utilizzare per la protezione con password.

Questa domanda è "double hashing" una password meno sicura rispetto alla semplice hashing di una volta? suggerisce che l'hashing di più volte può essere una buona idea, considerando come implementare la protezione con password per i singoli file? suggerisce di usare il sale.

Sto usando PHP. Voglio un sistema sicuro e veloce di crittografia delle password. Macinare una password un milione di volte può essere più sicuro, ma anche più lento. Come raggiungere un buon equilibrio tra velocità e sicurezza? Inoltre, preferirei che il risultato avesse un numero costante di caratteri.

  1. Il meccanismo di hashing deve essere disponibile in PHP
  2. Deve essere al sicuro
  3. Può usare il sale (in questo caso, tutti i sali sono ugualmente buoni? C'è un modo per generare dei buoni sali?)

Inoltre, dovrei memorizzare due campi nel database (uno usa MD5 e un altro usando SHA, per esempio)? Lo renderebbe più sicuro o meno sicuro?

Nel caso in cui non fossi abbastanza chiaro, vorrei sapere quali funzioni di hashing usare e come scegliere un buon sale per avere un meccanismo di protezione della password sicuro e veloce.

Domande correlate che non coprono la mia domanda:

Qual è la differenza tra SHA e MD5 in PHP
Crittografia semplice password
Metodi sicuri di memorizzazione delle chiavi, password per asp.net
Come implementeresti le password salate in Tomcat 5.5




Non memorizzerei l'hash della password in due modi diversi, perché il sistema è debole almeno quanto il più debole degli algoritmi di hash in uso.




Anche se la domanda è stata risolta, voglio solo ribadire che i sali usati per l'hashing dovrebbero essere casuali e non come l'indirizzo di posta elettronica come suggerito nella prima risposta.

Ulteriori spiegazioni sono disponibili http://www.pivotalsecurity.com/blog/password-hashing-salt-should-it-be-random/

Recentemente ho avuto una discussione se gli hash delle password salati con bit casuali sono più sicuri di quelli salati con sali ipotetici o conosciuti. Vediamo: Se il sistema che memorizza la password è compromesso e il sistema che memorizza il sale casuale, l'attaccante avrà accesso all'hash e al sale, quindi se il sale è casuale o meno, non importa. L'attaccante può generare tavoli arcobaleno pre-calcolati per rompere l'hash. Ecco la parte interessante: non è così banale generare tabelle pre-calcolate. Prendiamo un esempio del modello di sicurezza WPA. La password WPA non viene mai inviata al punto di accesso wireless. Invece, è sottoposto a hash con il tuo SSID (il nome della rete, come Linksys, Dlink, ecc.). Una buona spiegazione di come funziona è qui. Per recuperare la password dall'hash, è necessario conoscere la password e anche salt (nome della rete). Church of Wifi ha già tabelle di hash pre-calcolate con top 1000 SSID e circa 1 milione di password. La dimensione è di tutte le tabelle è di circa 40 GB. Come puoi leggere sul loro sito, qualcuno ha usato 15 array FGPA per 3 giorni per generare queste tabelle. Supponendo che la vittima stia usando il SSID come "a387csf3" e la password come "123456", sarà incrinata da quei tavoli? No! .. non può. Anche se la password è debole, le tabelle non hanno hash per SSID a387csf3. Questa è la bellezza di avere sale casuale. Distaccerà i cracker che prosperano su tavoli precompilati. Può fermare un hacker determinato? Probabilmente no. Ma l'uso di sali casuali fornisce ulteriore livello di difesa. Mentre siamo su questo argomento, discutiamo il vantaggio aggiuntivo di immagazzinare sali casuali su un sistema separato. Scenario n. 1: Gli hash delle password sono memorizzati sul sistema X e i valori saltati per l'hashing sono memorizzati sul sistema Y. Questi valori salt sono ipotizzabili o noti (ad es. Nome utente) Scenario n. 2: Gli hash delle password sono memorizzati sul sistema X e i valori di sale usati per l'hashing è memorizzato sul sistema Y. Questi valori di sale sono casuali. Nel caso in cui il sistema X sia stato compromesso, come puoi immaginare, c'è un enorme vantaggio nell'usare il sale casuale su un sistema separato (scenario n. 2). L'attaccante dovrà indovinare i valori di addizione per poter eseguire il crack degli hash. Se si utilizza un sale a 32 bit, sarà possibile richiedere 2 ^ 32 = 4.294.967.296 (circa 4.2 miliardi) di iterazioni per ogni password indovinata.




Sto usando openwall.com/phpass che è una semplice classe PHP con un solo file che potrebbe essere implementata molto facilmente in quasi tutti i progetti PHP. Vedi anche The H.

Per impostazione predefinita utilizzava la più potente crittografia disponibile implementata in Phpass, che è bcrypt e ricade su altre crittografie fino a MD5 per fornire compatibilità con le versioni precedenti di framework come Wordpress.

L'hash restituito potrebbe essere memorizzato nel database così com'è. L'esempio di utilizzo per la generazione di hash è:

$t_hasher = new PasswordHash(8, FALSE);
$hash = $t_hasher->HashPassword($password);

Per verificare la password, si può usare:

$t_hasher = new PasswordHash(8, FALSE);
$check = $t_hasher->CheckPassword($password, $hash);



Google dice che SHA256 è disponibile per PHP.

Dovresti assolutamente usare un sale. Mi consiglia di utilizzare byte casuali (e non limitarti a caratteri e numeri). Come di solito, più a lungo si sceglie, più sicuro, più lento diventa. 64 byte dovrebbero andare bene, credo.




Alla fine, il doppio hashing, matematicamente, non fornisce alcun vantaggio. In pratica, tuttavia, è utile per prevenire attacchi basati su tabelle arcobaleno. In altre parole, non è più vantaggioso dell'hash con un salt, che richiede molto meno tempo del processore nell'applicazione o sul server.




SHA1 e un sale dovrebbero essere sufficienti (a seconda, naturalmente, se si sta codificando qualcosa per Fort Knox o un sistema di login per la tua lista della spesa) per il prossimo futuro. Se SHA1 non è abbastanza buono per te, usa SHA256 .

L'idea di un sale è di sbilanciare i risultati dell'asportazione, per così dire. Ad esempio, è noto che l'hash MD5 di una stringa vuota è d41d8cd98f00b204e9800998ecf8427e. Quindi, se qualcuno con una memoria abbastanza buona vedrebbe quell'hash e sa che è l'hash di una stringa vuota. Ma se la stringa è salata (ad esempio, con la stringa " MY_PERSONAL_SALT"), l'hash per la 'stringa vuota' (cioè " MY_PERSONAL_SALT") diventa aeac2612626724592271634fb14d3ea6, quindi non ovvio per il backtrace. Quello che sto cercando di dire è che è meglio usare qualsiasi sale, piuttosto che non farlo. Pertanto, non è troppo importante sapere quale sale usare.

In realtà ci sono siti web che fanno proprio questo : puoi nutrirlo con un hash (md5), e sputa un testo in chiaro noto che genera quel particolare hash. Se si dovesse accedere a un database che memorizza gli hash md5, sarebbe banale inserire l'hash per l'amministratore in tale servizio ed effettuare il login. Tuttavia, se le password fossero state salate, tale servizio sarebbe diventato inefficace.

Inoltre, il double-hashing è generalmente considerato come metodo cattivo, perché diminuisce lo spazio dei risultati. Tutti gli hash popolari sono a lunghezza fissa. Quindi, puoi avere solo un valore finito di questa lunghezza fissa, ei risultati diventano meno vari. Questo potrebbe essere considerato come un'altra forma di salatura, ma non lo consiglierei.




Related

php security passwords hash protection