
Once again, when we finished conducting an information security audit of a web project, my personal barrel of anger overflowed with indignation so that it overflowed into this post.
I will try to very concisely and quickly describe the situation with hashes.
')
Immediately I will determine which task of using hashes I will consider - user authentication. No password recovery tokens, no request authentication, not something else. This is also not an article about the protection of the data channel, so the comments on the challenge-response and SSL are inappropriate!
Materiel (short)
Hash = hash function - (convolution) is the function of uniquely displaying a string (of any length) onto a finite set (a string of a given length).
The number (string) hash itself is the result of calculating the hash function on the data.
There are cryptographic and non-cryptographic (classified separately, for example, checksums) hash functions.
For cryptographic hashes there are three additional conditions that distinguish them from all others:
- Irreversibility: for a given hash value m, it should be computationally impractical to find a data block X for which H (X) = m.
- Resistance to collisions of the first kind: for a given message M must be computationally impracticable to pick up another message N, for which H (N) = H (M).
- Resistance to collisions of the second kind: it should be computationally impracticable to pick up a pair of messages ~ (M, M '), having the same hash
Learn more -
en.wikipedia.org/wiki/%D0%A5%D0%B5%D1%88%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0BB%D0%B8 % D0% B5It is not necessary for an application developer to delve into the intricacies of cryptography; it is enough to remember which hash functions (algorithms by name) can now be used and which ones no longer exist. MD5 - no longer possible, colleagues - use bcrypt / scrypt.
In web applications, among other things, hash functions are used to securely store secrets (passwords) in a database.
It is the hash function that becomes your last stronghold if the attacker was able to reduce the attack to a local attack on the authentication system. About online attacks (brute force HTTP passwords with requests), maybe someone else will write later.
Below are the requirements that your hash in the database must meet:
- resistance to brute-force attacks (brute force and dictionary search)
- inability to search for identical passwords of different users by hashes
To fulfill the first requirement, you must use persistent (not in the 90s!) Hash functions.
To perform the second, a random string (salt) is added to the password before hashing. Thus, the two users with the password “123456” will have different salts “salt1” and “salt2”, and accordingly the hash functions from “123456sol1” and “123456sol2” in the database will also be different.
Now a little about the storage system - both the salt and the hash itself are stored in the database.
That is, by gaining access to the DBMS, the attacker gets both hash values and salt values.
Use the local parameter!
To make life difficult when brute-force attacks, you should add salt to the password, and not vice versa (for people who write from left to right, of course).
Since the hash function, as a rule, is calculated sequentially by a string (the requirements of the algorithm’s threading), it will be easier for an attacker to search for “salted” hashes when the sub-phrase begins with salt.
It is simpler because he (the attacker) can predict the hash (salt) in advance and then count the hash (salt) + hash (password) much faster (almost at the same speed as the hash (password)). For all passwords that he will sort through.
In order to further complicate the life of an attacker, Solar Designer
www.openwall.com/presentations/YaC2012-Password-Hashing-At-Scale/mgp00005.html prompts you to enter another thing called a local parameter.
This is essentially the "second salt" is added to all (passwords + salt) constructs, and is the same for all hashes in the database. What is the trick? The fact that there is no local parameter in the database. This is a constant of the system, which is stored in the memory of the application, where it gets from the config (in any way, just not from the database).
A very simple and effective measure that allows you to almost completely eliminate the brute force attack on the data of only one hash store (without knowing the local parameter).
The only time we (ONsec) broke the hashes with a local parameter, while developing attack tactics on the local parameter itself (registering in the application, then looking for our hash, salt (we already know our password) and sort out the LP). And in vain. At lengths of 16+ bytes for modern hashing functions, this is very expensive in terms of hardware. As a result, it turned out to be easier to compromise the authentication system (put yourself a role = admin in the database via UPDATE;))
I highly recommend reading the presentation:
www.openwall.com/presentations/YaC2012-Password-Hashing-At-Scale/mgp00001.htmlProtect your storage safely and correctly!
Conclusion
I would be a realist - naturally, no one would rewrite their projects for the sake of "some" hashes. But new projects can be written on scrypt / bcrypt. And also - implement a local parameter even on weak MD5 - it really helps, it is checked :)
In the transition to a different type of hashing, in addition to labor costs, there is often a question of performance. Indeed, more robust algorithms consume more resources. Test before deploying user authentication speeds per second for your workloads (for most large projects, the transition to scrypt was painless). The choice of a particular ideal type of hash in a particular situation can vary greatly. So, for example, DBOs are increasingly choosing iron solutions for generating hashes with a given speed.
In conclusion, I cite the speeds for searching hashes (units of measurement - megaheshes per second, that is, the number) received on an AMD Radeon 7990 card worth less than $ 1,000 (even at the old rate):
- MD5: 16000 M / s
- SHA-1: 5900 M / s
- SHA256: 2050 M / s
- SHA512: 220 M / s
- NTLM: 28400 M / s
- bcrypt: 8.5 k / s
And regarding the effectiveness of bcrypt enumeration, I also recommend that you familiarize yourself with
www.openwall.com/presentations/Passwords13-Energy-Efficient-Cracking/Passwords13-Energy-Efficient-Cracking.pdf