
Today we'll see how best to store passwords in the database and how well-known platforms solve this problem.
Plaintext
When the question arose of storing passwords, of course, the first idea was simply to write them in clear text in the appropriate table in the database. And everything would be fine if the clients could not get access to it directly. But, unfortunately, this well-known SQL injection sometimes works in various web applications, not to mention other potential vulnerabilities. In matters of security, it is generally accepted to assume the worst and prepare an action plan and protection even in such a case. We assume that the attacker has found a loophole in the web application, in one way or another happily unloads the table with the names and passwords of users and then already controls them as he pleases. In general, its further actions may be as follows:
- performing illegitimate actions on behalf of users using their credentials on a vulnerable resource: for example, a bank card is attached to an account and now an attacker can use it;
- an attempt to use the received password on other resources: by no means all the users, following the advice, come up with new passwords for different services each time;
- an attempt to identify the password generation rule and move on to the second paragraph: some form some kind of password composition rule; as a result, the passwords on different resources are different, but they obey the same rule that can be detected;
- privilege escalation: an administrator password can also be stored in the same table, with the knowledge of which you can sometimes get complete control over the server.
Encryption Hashing
The idea immediately turns out to be not so good. What to do? It would be great to store passwords in encrypted form. Then, even if they are removed, they will not be able to recover, or at least spend too much time on it. Here the choice arises between two branches of development: encrypt passwords or hash. The developers stopped at the second, and, in principle, it is clear why. Let's compare our applicants according to different characteristics:
- Complexity Encryption takes more time, and no matter what conversion we choose, it will have to be done every time the password is checked. One of the requirements for hash functions is the speed of execution.
- The length of the output values. The result of encryption has a variable length, the result of hashing is always the same, and storing data of uniform size in the database is very convenient. Not to mention that the length of the password in encrypted form will give some information about the length of the original password. The same length, however, leads to the possibility of collisions, but more on that below.
- Key management. Encryption requires a key, which also has to be stored somewhere and hope that no one will find it. In any case, the generation and management of keys is a separate story (they should not be weak, they should be changed regularly, and so on).
- The possibility of conflict. When encrypting, the output from the various input data will also always be different. With hashing, this is not always the case. The constant hash length means that the set of output values of the hash function is limited, which leads to the possibility of collision. That is, for example, the user is really confused and invented himself a really cool long password, in which there are special characters, and numbers, and letters in lower and upper case. The attacker enters into the password field at least a cool password “admin”. The server for checking and comparing hashes hashed it. Hashes matched. It's a shame.
Thus, with a score of 3: 1, hashing wins. But can we stop at this?
The answer is no.
Hash Passwords Attacks
So, the attacker got our table with usernames and passwords. Passwords are now hashed, but this does not stop our attacker, and he seriously intends to recover them. His possible actions are:
- Dictionary brute-force: if the attacker didn’t work with the administrator’s reference password, he would turn to the dictionary of popular passwords and try his luck with their hashes;
- rainbow tables: in general, today, he may not need to calculate anything at all and go through the dictionary. It is enough to refer to the rainbow tables lying on the network. The rainbow tables contain the hash values already computed by someone before and the corresponding input data. It is important to note that due to collisions, the password that the rainbow table suggests will not necessarily be the one that the user uses. The precomputed values are already for MD5, SHA1, SHA256, SHA512, as well as for their modifications and some others. You can try to convert a hash, for example, here ;
- full brute force: if this does not help, you have to resort to brute force and go through all possible passwords in a row until the calculated hashes finally match.
In the most general case, the attacker will have to crack passwords. And here his success will depend, among other things, on the speed of the calculation of the hash function. Comparison of the time of the hashes can be found
here . For example, Java hash functions on 64-bit Windows 10 with 1 core Intel i7 2.60GHz and 16GB RAM were run a million times to calculate a hash of 36 characters. They showed the following results:
MD5 - 627 ms
SHA-1 - 604 ms
SHA-256 - 739 ms
SHA-512 - 1056 ms
But today, brute force can be parallelized and run many times faster on the GPU (as well as on the APU, DSP and FPGA). However, besides choosing a longer algorithm and a longer output, you can do something else.
Hash Hash
To prevent the intruder from using the ready-made rainbow tables, there is a password hashing technique several times. That is, we calculate the hash from the hash from the hash from the hash ... and so n times (you really don’t need to get involved with it, because with a normal user password check, the server will also have to do it). Now it’s so easy to find a password on the rainbow table, and the time for brute force will increase significantly. But nothing can stop an attacker from generating a rainbow table using a password dictionary, knowing the hashing algorithm. Moreover, for the most popular combinations of this method, such tables have already been generated:

"
Add salt to taste
In order that he could not do this, passwords are now hashed with the addition of salt.
Salt is an additional random string that is assigned to a password and is hashed along with it. From the hash obtained in this way, the password cannot be recovered from the rainbow table. Knowing the salt and the output hash, the attacker is doomed to brute force and no pre-calculated tables will most likely help him.
Taxonomy salting passwords:
1. By the principle of salting:
- unique salt for each user: individual for each user - so if the attacker becomes known to the attacker, you will have to wrestle each password separately. And besides, even if two users think the same way and come up with identical passwords, the hashes will still be different on the output;
- global salt: the same for all, used for all hashes;
- both.
2. According to the salt storage method:
- in the database: as a rule, individual salts are stored in the same database as password hashes; often even on the same line;
- in the code (read: in the config): global salt is usually not stored in the database, but, for example, in the config, so that the offender had to spend time on its selection.
We assume that the individual salts of users are stored in the database, the global salt in the config. The attacker gained access to the database, and he knows all the hashes and their corresponding salts (global salt is not stored in the database, and he does not know it). So, if you combine all the methods, then in order to get the passwords in the clear, as was the case in the first systems, he, being extremely goal-oriented, will face the following obstacles:
- He does not know the global salt, so it will have to be brutalized.
- He knows the users ’salts, but he doesn’t have the prepared tables with these salts, so the passwords will have to be played.
- This process will take even longer due to the need to hash hashes n times.
How passwords are stored different CMS
Wordpress
Prior to version 3.x, passwords were simply hashed with MD5. The phpass library is now used. By default, the salt is attributed to the front password and the resulting string is hashed MD5 2 ^ 8 times.
Joomla
Prior to version 1.0.12, MD5 was used. The phpass library is used, the default is bcrypt with salt and 2 ^ 10 repetitions.
Drupal
Up to version 6 md5 without salt. The phpass library is used. The default is salty sha512 with 2 ^ 16 repetitions.
Silverstripe
Uses salty Blowfish with 2 ^ 10 repetitions.
Umbraco
Uses HMACSHA256 with salt. Uses the second global salt specified in the config.