Hashing delle password in modo sicuro

Questa sezione spiega le ragioni per cui usare le funzioni di hashing per proteggere le password, e come farlo in modo efficace.

Perché dovrei applicare l'hash alle password fornite dagli utenti?

L'hashing delle password è una delle considerazioni di sicurezza più basilari che devono essere fatte quando si progetta qualsiasi applicazione o servizio che accetta password dagli utenti. Senza hashing, qualsiasi password memorizzata può essere rubata se l'archivio dati viene compromesso, e poi usata immediatamente per compromettere non solo l'applicazione o il servizio, ma anche gli account degli utenti su altri servizi, se non usano password uniche.

Applicando un algoritmo di hashing alle password degli utenti prima di memorizzarle, diventa implausibile per qualsiasi attaccante determinare la password originale, pur essendo ancora in grado di confrontare l'hash risultante con la password originale in futuro.

È importante notare, tuttavia, che l'hashing delle password le protegge solo dall'essere compromesse nell'archivio dati, ma non le protegge necessariamente dall'essere intercettate da codice malevolo iniettato nell'applicazione o nel servizio stesso.

Perché le funzioni di hashing comuni come md5() e sha1() non sono adatte per le password?

Gli algoritmi di hashing come MD5, SHA1 e SHA256 sono progettati per essere molto veloci ed efficienti. Con le tecniche moderne e l'equipaggiamento informatico, è diventato banale fare brute force sull'output di questi algoritmi, per determinare l'input originale.

A causa della rapidità con cui un computer moderno può invertire questi algoritmi di hashing, molti professionisti della sicurezza sconsigliano fortemente il loro uso per l'hashing delle password.

Come dovrebbero essere hashate le password, se le funzioni di hash comuni non sono adatte?

Quando si hashano le password, le due considerazioni più importanti sono il costo computazionale e il salt. Più è computazionalmente costoso l'algoritmo di hashing, più tempo ci vorrà per fare brute force sul suo output.

PHP fornisce un'API nativa per l'hashing delle password che gestisce in modo sicuro sia l'hashing che la verifica delle password in modo sicuro.

L'algoritmo suggerito da usare per l'hashing delle password è Blowfish, che è anche il default usato dall'API di hashing delle password, poiché è significativamente più costoso computazionalmente rispetto a MD5 o SHA1, pur rimanendo scalabile.

La funzione crypt() è anche disponibile per l'hashing delle password, ma è raccomandata solo per l'interoperabilità con altri sistemi. Invece, è fortemente incoraggiato l'uso dell' API nativa per l'hashing delle password quando possibile.

Cos'è un salt?

Un salt crittografico è un dato che viene applicato durante il processo di hashing per eliminare la possibilità che l'output venga cercato in una lista di coppie pre-calcolate di hash e relativi input, nota come rainbow table.

In termini più semplici, un salt è un po' di dati aggiuntivi che rende gli hash significativamente più difficili da craccare. Ci sono diversi servizi online che forniscono liste estese di hash pre-calcolati, così come l'input originale per quegli hash. L'uso di un salt rende implausibile o impossibile trovare l'hash risultante in una di queste liste.

password_hash() creerà un salt casuale se non ne viene fornito uno, e questo è generalmente l'approccio più semplice e sicuro.

Come vengono memorizzati i salt?

Quando si usa password_hash() o crypt(), il valore restituito include il salt come parte dell'hash generato. Questo valore dovrebbe essere memorizzato così com'è nel database, poiché include informazioni sulla funzione hash che è stata usata e può quindi essere passato direttamente a password_verify() quando si verificano le password.

Avviso

password_verify() dovrebbe sempre essere usato invece di ri-hashare e confrontare il risultato con un hash memorizzato per evitare attacchi di timing.

Il seguente diagramma mostra il formato di un valore restituito da crypt() o password_hash(). Come si può vedere, sono auto-contenuti, con tutte le informazioni sull'algoritmo e sul salt necessarie per la futura verifica della password.


        I componenti del valore restituito da password_hash e crypt: in
        ordine, l'algoritmo scelto, le opzioni dell'algoritmo, il salt usato,
        e la password hashata.

add a note

User Contributed Notes 3 notes

up
150
alf dot henrik at ascdevel dot com
11 years ago
I feel like I should comment some of the clams being posted as replies here.

For starters, speed IS an issue with MD5 in particular and also SHA1. I've written my own MD5 bruteforce application just for the fun of it, and using only my CPU I can easily check a hash against about 200mill. hash per second. The main reason for this speed is that you for most attempts can bypass 19 out of 64 steps in the algorithm. For longer input (> 16 characters) it won't apply, but I'm sure there's some ways around it.

If you search online you'll see people claiming to be able to check against billions of hashes per second using GPUs. I wouldn't be surprised if it's possible to reach 100 billion per second on a single computer alone these days, and it's only going to get worse. It would require a watt monster with 4 dual high-end GPUs or something, but still possible.

Here's why 100 billion per second is an issue:
Assume most passwords contain a selection of 96 characters. A password with 8 characters would then have 96^8 = 7,21389578984e+15 combinations.
With 100 billion per second it would then take 7,21389578984e+15 / 3600 = ~20 hours to figure out what it actually says. Keep in mind that you'll need to add the numbers for 1-7 characters as well. 20 hours is not a lot if you want to target a single user. 

So on essence:
There's a reason why newer hash algorithms are specifically designed not to be easily implemented on GPUs.

Oh, and I can see there's someone mentioning MD5 and rainbow tables. If you read the numbers here, I hope you realize how incredibly stupid and useless rainbow tables have become in terms of MD5. Unless the input to MD5 is really huge, you're just not going to be able to compete with GPUs here. By the time a storage media is able to produce far beyond 3TB/s, the CPUs and GPUs will have reached much higher speeds.

As for SHA1, my belief is that it's about a third slower than MD5. I can't verify this myself, but it seems to be the case judging the numbers presented for MD5 and SHA1. The issue with speeds is basically very much the same here as well.

The moral here:
Please do as told. Don't every use MD5 and SHA1 for hasing passwords ever again. We all know passwords aren't going to be that long for most people, and that's a major disadvantage. Adding long salts will help for sure, but unless you want to add some hundred bytes of salt, there's going to be fast bruteforce applications out there ready to reverse engineer your passwords or your users' passwords.
up
28
swardx at gmail dot com
9 years ago
A great read..

https://nakedsecurity.sophos.com/2013/11/20/serious-security-how-to-store-your-users-passwords-safely/

Serious Security: How to store your users’ passwords safely

In summary, here is our minimum recommendation for safe storage of your users’ passwords:

    Use a strong random number generator to create a salt of 16 bytes or longer.
    Feed the salt and the password into the PBKDF2 algorithm.
    Use HMAC-SHA-256 as the core hash inside PBKDF2.
    Perform 20,000 iterations or more. (June 2016.)
    Take 32 bytes (256 bits) of output from PBKDF2 as the final password hash.
    Store the iteration count, the salt and the final hash in your password database.
    Increase your iteration count regularly to keep up with faster cracking tools.

Whatever you do, don’t try to knit your own password storage algorithm.
up
-4
tamas at microwizard dot com
4 years ago
While I am reading the comments some old math lessons came into my mind and started thinking. Using constants in a mathematical algorythms do not change the complexity of the algorythm itself.

The reason of salting is to avoid using rainbow tables (sorry guys this is the only reason) because it speeds up (shortcuts) the "actual" processing power.
(((Longer stored hashes AND longer password increases complexity of cracking NOT adding salt ALONE.)))

PHP salting functions returns all the needed information for checking passwords, therfore this information should be treated as constant from farther point of view. It is also a target for rainbow tables (sure: for much-much larger ones).

What is the solution?
The solution is to store password hash and salt on different places.
The implementation is yours. Every two different places will be good enough.

Yes, it will make problems for hackers. He/she needs to understand your system. No speed up for password cracking will work for him/her without reimplementing your whole system.

This is my two cent.
To Top