I could really use some clarification as to how using a random salt protects against rainbow table attacks. It just isn't clicking for me.
Suppose there is a dumb application that requires passwords to be exactly five characters or less, and that salts those passswords with a nine-character random salt. If I have a rainbow table that has precomputed hashes of all character combinations 14 characters or less, how does the random salt provide any additional security? In this case won't the hashed value of the random salt + password combo. be present in the rainbow table?
I have read multiple places that using a salt would force the cracker to generate an entirely new rainbow table; similarly, a random per-password salt would require a new rainbow table for each salt. Why?
If someone truly has a rainbow table containing the hash of all possible character combinations, then no, salting is of no help. But even assuming just A-z, a-z, 0-9 as valid characters, that's 6214 = 1.2x1025 14-character passwords. So that's 170 billion petabytes of storage required.
Given that that's not feasible, the attacker must have a much smaller table, containing only the most likely character strings (e.g. all the words in a dictionary, intermingled with numbers, etc.). If you add a salt, then this table becomes useless. If the salt is fixed (and known), then the attacker could recompute a new table. But if each password has a different salt, then that won't work either.
One of the faster yet to some extent effective ways to see what a password is by creating a hash on all words in a dictionary, for example. People who try to crack passwords know what they're looking for and due to limited computing speeds they narrow their search down to often used passwords. By using a salt these often used words will never truly be used as a password.
Related
I'm very close to understanding exactly how the compare function of bcrypt works, but there are a few missing holes in my knowledge.
My understanding so far:
brcypt gens a hashed password using a plain text password and a randomly generated salt. The hashed password is a combination of the bcrypt version, the hashed salt and the concatenated hashed plain text password. When a user logs in, their plain text password is ran through the compare function. At that point, bcrypt knows how many characters in the hash and from what offset to begin to slice the hashed salt out of the full hash. It then concatenates the salt with the passed in plain text password, running it through the hashing algorithm to arrive at the final hashed string. The hashed string is compared to the hashed string in the database and if there is an exact character match, the password is correct.
2 questions..
Aren't hashes supposed to be impossible to reverse? If so, then how does bcrypt know how to decrypt the hashed salt and then use it to hash the incoming plain text password. That doesn't make any logical sense to me.
If brcypts algorithm is written such that it can always create a hashed salt that it always knows how to decrypt, can't hackers just use that algorithm to grab every hashed password from a database and slice the salts out? Then it could create a rainbow table for every salt and crack each individual password? That seems logical to me.
Pardon if my question doesn't make any sense. Happy to edit.
Read articles, read stack overflow questions, watched videos and asked a senior engineer.
A rainbow table is a pre-compiled list of every password you can find, and their hash.
Your rainbow table has:
hash("password1234")
hash("hunter2")
hash("correct horse battery staple")
But it doesn't have:
hash("ȃ#🙍♽😔ƅ😠☸☑+password1234")
hash("ȃ#🙍♽😔ƅ😠☸☑+hunter2")
hash("ȃ#🙍♽😔ƅ😠☸☑+correct horse battery staple")
You could go ahead and create a rainbow table that contains every password for this salt. But that's just called a Brute Force attack.
And this second rainbow table doesn't help you with the next website that chooses a different salt:
hash("®óó»♠☘☛🙈Ũh+password1234")
hash("®óó»♠☘☛🙈Ũh+hunter2")
hash("®óó»♠☘☛🙈Ũh+correct horse battery staple")
And to eliminate all the guesswork, and all the difficulty of storing a salt, and deciding a salt: modern password hashing algorithms generate a different random salt for every password for you, and store the salt in the resulting hash string for you:
hash("ȼŚ😑¥dĥ😥®µ+password1234")
hash("ČɆǝ%ËȌÁpmLȫ+hunter2")
hash("♼♄ș♰;⚁f)²ŋì😱³UÍ+correct horse battery staple")
Which is in essence what bcrypt does; it generates a different salt for every password.
Let's say we don't use password_hash and use crypt() with sha512 instead to hash passwords. We need to add salt to the password, so an attacker couldn't use a rainbow table attack. Why the salt has to be good and very random as stated in many SO answers? Even if salt differs by a little or not very random, it will still give a totally different hash from others. So, an attacker won't know who uses the same passwords and he still won't be able to create just one rainbow table.
Computing and storing a strong salt requires minimal effort yet reduces the chances of a rainbow table having being pre-computed with the salt astronomically small.
If the salt was a 3 digit number it would be feasible that an attacker could have pre-computed rainbow tables for all possible salt combinations. If the salt is a random 24 character alpha-numeric string then the chances an attacker could pre-compute this for all possible salts are practically zero.
A salt is supposed to be unique, must be long enough, and should be unpredictable. Randomness is not necessary, but it is the easiest way for a computer to meet those requirements. And it is not the purpose of a salt to be secret, a salt fulfills its purpose even when known.
Uniqueness means that it should not only be unique in your database (otherwise you could use a userid), it should be unique worldwide. Somebody could create rainbowtables for salts like e.g. 1-1000 and would be able to retrieve passwords for all accounts with those userids (often admin accounts have low userids).
Long enough: If the salt is too short (too few possible combinations), it becomes profitable again to build rainbow-tables. Salt and password together can then be seen as just a longer password, and if you can build a rainbow-table for this longer passwords, you also get the shorter original passwords. For very strong and long passwords, salting would actually not be necessary at all, but most human generated passwords can be brute-forced because they are short (people have to remember them).
Also using salts derrived from other parameters can fall into this category. Only because you calculate a hash from the userid, this doesn't increase the possible combinations.
Unpredictability is a bit less important, but imagine once more the case that you use the userid as salt, an attacker can find out what the next few userids will be, and can therefore precalculate a narrow number of rainbow-tables. Depending of the used hash-algorithm this can be applicable or not. He has a time advantage then, can retrieve the password immediately. More of a problem will be, if the admin accounts used a predictable salt.
So using a really random number, generated from the OS random source (dev/urandom), is the best you can do. Even when you ignore all reasons above, why should you use a derived salt when there is a better way, why not use the best way you know?
Hearing about all the recent hacks at big tech firms, it made me wonder their use of password storage.
I know salting + hashing is accepted as being generally secure but ever example I've seen of salting has the salt key hard-coded into the password script which is generally stored on the same server.
So is it a logical solution to hash the user's password initially, pass that hash to a "salting server" or some function stored off-site, then pass back the salted hash?
The way I I'm looking at it is, if an intruder gains access to the server or database containing the stored passwords, they won't immediately have access to the salt key.
No -- salt remains effective even if known to the attacker.
The idea of salt is that it makes a dictionary attack on a large number of users more difficult. Without salt, the attacker hashes all the words in a dictionary, and sees which match with your users' hashed paswords. With salt, he has to hash each word in the dictionary many times over (once for each possible hash value) to be certain of having one that fits each user.
This multiplication by several thousand (or possibly several million, depending on how large a salt you use) increases the time to hash all the values, and the storage need to store the results -- the point that (you hope) it's impractical.
I should add, however, that in many (most?) cases, a very large salt doesn't really add a lot of security. The problem is that if you use, say, a 24 bit salt (~16 million possible values) but have only, say, a few hundred users, the attacker can collect the salt values you're actually using ahead of time, then do his dictionary attack for only those values instead of the full ~16 million potential values. In short, your 24-bit salt adds only a tiny bit of difficulty beyond what a ~8 bit salt would have provided.
OTOH, for a large server (Google, Facebook, etc.) the story is entirely different -- a large salt becomes quite beneficial.
Salting is useful even if intruder knows the salt.
If passwords are NOT salted, it makes possible to use widely available precomputed rainbow tables to quickly attack your passwords.
If your password table was salted, it makes it very difficult to precompute rainbow tables - it is impractical to create rainbow table for every possible salt.
If you use random salt that is different for every password entry, and put it in plaintext right next to it, it makes very difficult for intruder to attack your passwords, short of brute force attack.
Salting passwords protects passwords against attacks where the attacker has a list of hashed passwords. There are some common hashing algorithms that hackers have tables for that allow them to look up a hash and retrieve the password. For this to work, the hacker has to have broken into the password storage and stolen the hashes.
If the passwords are salted, then the attacker must re-generate their hash tables, using the hashing algorithm and the salt. Depending on the hashing algorithm, this can take some time. To speed things up, hackers also use lists of the most common passwords and dictionary words. The idea of the salt is to slow an attacker down.
The best approach to use a different salt for each password, make it long and random, and it's ok to store the salt next to each password. This really slows an attacker down, because they would have to run their hash table generation for each individual password, for every combination of common passwords and dictionary words. This would make it implausible for an attacker to deduce strong passwords.
I had read a good article on this, which I can't find now. But Googling 'password salt' gives some good results. Have a look at this article.
I would like to point out, that the scheme you described with the hard-coded salt, is actually not a salt, instead it works like a key or a pepper. Salt and pepper solve different problems.
A salt should be generated randomly for every password, and can be stored together with the hashed password in the database. It can be stored plain text, and fullfills it's purpose even when known to the attacker.
A pepper is a secret key, that will be used for all passwords. It will not be stored in the database, instead it should be deposited in a safe place. If the pepper is known to the attacker, it becomes useless.
I tried to explain the differences in a small tutorial, maybe you want to have a look there.
Makes sense. Seems like more effort than worth (unless its a site of significant worth or importance) for an attacker.
all sites small or large, important or not, should take password hashing as high importance
as long as each hash has its own large random salt then yes it does become mostly impracticable, if each hash uses an static salt you can use Rainbow tables to weed out the users hashs who used password1 for example
using an good hashing algorithm is also important as well (using MD5 or SHA1 is nearly like using plaintext with the mutli gpu setups these days) use scrypt if not then bcrypt or if you have to use PBKDF2 then (you need the rounds to be very high)
I am having difficulty understanding how a salt which is appended to a hash helps improve the security when a database of passwords or other important information is compromised.
If the salt is, for example, "hello", and is appended to the password "password" then the salt and password are stored together, "hellopassword" and hashed to produce:
94e66f94517d606d5ad6d9191b980408952f2ed2 (sha1)
with the salt then appended:
hello$94e66f94517d606d5ad6d9191b980408952f2ed2
How is this more secure? The attacker knows the salt so can now compute the passwords with little extra difficulty... right? Or am I fundamentally misunderstanding something?
No, not with "little extra difficulty" - with potentially significantly more difficulty.
Imagine there are two billion common passwords. It's easy to hash all of those and store the results. Then if you have an unsalted password hash, you can just check which common passwords match the given hash.
Now compare that with a salted hash... now you have two billion common passwords, but also several billion possible salts. Computing all the possible salt/password combinations will take much, much longer - hopefully becoming infeasible.
Additionally, it means that even if two people have the same password, they are very likely to have different hashes - so carelessness of one user in revealing their password doesn't risk the security of the other.
See the Wikipedia entry (if you haven't already) for more on this.
salt helps in 2 ways:
1) When two (or more) people use the same password, without salt you can see who uses the same password (the hashes are all the same). So in theory, if that person knows one of those person's passwords he knows everyone's passwords with the same hash. This is a minor reason.
2) The main reason is to prevent attacks commonly called dictionary attacks or rainbow attacks. In these attacks someone uses a database of pre-calculated hashes for common passwords. Often times these databases are gigs in size. But it is very easy at that point to just do a lookup for the hashes you have (the hashed password) against the list of pre-calculated hashes and see what the associated password is.
By using a salt value (typically you want this to be a random number) the hash won't match the dictionary (the chance of them pre-calculating all passwords with all possible salt values is exponentially more difficult). So even if your user uses an easily attacked password, say "Password", which is pretty much guaranteed to be any in any password dictionary/rainbow table, by pre-pending your random salt value you make the hash pretty much guaranteed to be useless to the attacker. Meanwhile for you, since the salt is just stored in cleartext, it makes it very easy for you to add it to your cleartext for your comparison of the password the user entered.
The salt isn't appended to the hash, its appended to the password THEN hashed. This is more secure because hackers have to know the salt and the actual password, which you should both protect heavily. :D
Ok, I’m trying to understand the reason to use salt.
When a user registers I generate a unique salt for him/her that I store in DB. Then I hash it and the password with SHA1. And when he/she is logging in I re-hash it with sha1($salt.$password).
But if someone hacks my database he can see the hashed password AND the salt.
Is that harder to crack than just hashing the password with out salt? I don’t understand …
Sorry if I’m stupid …
If you don't use a salt then an attacker can precompute a password<->hash database offline even before they've broken into your server. Adding a salt massively increases the size of that database, making it harder to perform such an attack.
Also, once they've broken in they can guess a commonly used password, hash it, and then check all of the passwords in the database for a match. With a different salt for each user, they can only attack one password at a time.
There's an article at Wikipedia about salts in cryptography.
Another intention behind the use of a salt is to make sure two users with the same password won't end up having the same hash in the users table (assuming their salt are not the same). However, the combination of a salt and a password may lead to the same "string" or hash in the end and the hash will be exactly the same, so make sure to use a combination of salt and password where two different combination won't lead to the same hash.
If an attacker creates a giant table of hash values for plaintext passwords, using a salt prevents him from using the same table to crack more than one password. The attacker would have to generate a separate table for each salt. Note that for this to actually work propertly, your salt should be rather long. Otherwise the attacker's precomputed table is likely to contain the salt+password hash anyway.