The key insight from the above is that we can thwart simple dictionary attacks by hashing inputs that are unlikely to have been used to generate a hash dictionary. One possibility would be to ask users to use strong passwords with a mix of uppercase, lowercase, digits and punctuation, but we don't want to have to depend on users to do that. (Anyway, the more complicated the passwords are, the more likely the user is to write the password down on a Post-It, which creates its own security issues.) So what else can we do?
The answer is that we can concatenate the plaintext with some given additional piece of text, known as a "salt," and then hash and store the result. The salt should be something that you're pretty sure wouldn't be used in generating a generic hash database. That way there's no chance that somebody could use an existing dictionary to attack your passwords.
Let's say, for instance, that we choose iamJeLLy%Dans0R as our salt. Then we can generate safer hashes as follows:
| Plaintext password | Password + salt | MD5 hash of password + salt |
|---|---|---|
friend |
friend{iamJeLLy%Dans0R} |
a62dc48775f623e180dd0ff2bc870b24 |
friends |
friends{iamJeLLy%Dans0R} |
ec844e0a820ae2e4444f70c5a447c467 |
password |
password{iamJeLLy%Dans0R} |
1d7eed225b27a9cd075478e7d5de29a6 |
I pledge allegiance to the flag |
I pledge allegiance to the flag{iamJeLLy%Dans0R} |
cd7e0f644ebecb7c7c3558c71a8f7a86 |
Call me an optimist, but I am pretty sure you are not going to find any of those hashes in an existing hash database. So now we are bulletproof, yes?
No, not really. (And there probably isn't such a thing when it comes to security.) You may have noticed that I kept saying that the hashes wouldn't appear in an existing hash database. That's the clue you need in order to figure out how the attacker can still get at your passwords. Assume also that the attacker knows the salt value, which isn't necessarily unrealistic since he does after all have access to your passwords. Maybe he has access to the salt too. Do you see the attack?
All the attacker needs to do is generate a new lookup table. He grabs a file containing hundreds of thousands of dictionary words, appends each one with the salt, computes the hash and finally creates the lookup entry. Ugh!
How realistic is that? For casual observers and novice attackers, it's unlikely. But if somebody is fairly determined to get the passwords, it's not unlikely at all. Dictionary files in multiple languages are after all readily available—see, e.g., http://www.winedt.org/Dict/—and anyway, it's not even necessary to process the entire dictionary. Just choose say 1,000 common words and do those. That'll get you pretty far if there are enough passwords in the password database.
You might wonder why we would even look at this approach, given that it's easy enough to defeat. There are multiple reasons. First, even though it's easy to defeat, it does in fact create an extra obstacle to getting at the passwords, and that obstacle is sufficiently frustrating that it will filter out attackers who aren't at least fairly determined and knowledgeable. Secondly, we assumed that the salt was known. If you're able to keep the salt a secret (e.g., store it separately from the password database), then you have the makings of a practically impenetrable password storage scheme. The problem however is keeping the salt secret; presumably either the developers or the admins will know it. But if you're able to pull that off, go for it.
The third reason is that we can use a modified version of our salt approach to make password recovery even more difficult still. The trick is to use different salts for different passwords. Let's see how that works.