del.icio.us Digg DZone Reddit StumbleUpon
Storing Passwords Securely - Willie Wheeler
« Previous | 1 | 2 | 3 | 4 | 5 | Next »

Using hashes and fixed salts to protect passwords from slightly-determined attackers

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
Table 3. Salting and MD5-hashing your passwords for added protection

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.

Social bookmarks: del.icio.us Digg DZone Reddit StumbleUpon
« Previous | 1 | 2 | 3 | 4 | 5 | Next »

Comments (12)

Great article, very timely given the continuous stream of new's about security exploit's and problem's. Another item consideration might be to use per user random salt's. If you continue down this line of tutorials If i may suggest a topic, how to address API security, and also browser to server security.

Thanks
By Aaron Raddon on Sep 1, 2008 at 9:13 PM PDT
Hi Aaron, really nice to see you here. :-D Thanks for the nice words about the article. I agree that security articles are timely and I'm afraid they probably always will be.

Per-user random salts are a great idea, especially in the case where you are somehow able to keep the random salts separate from the passwords. If the passwords are compromised but the salts are not, having random salts will be much more effective than using a sequence-based PK, because the attacker won't know what needs to be hashed, and a brute-force approach would probably be infeasible if the number of salt bits is sufficiently high. I don't myself know best practices around keeping passwords and per-user salts separate--it seems to me that if you store the salts and the passwords in the same table then the attacker will typically have either both the password and the salt or neither--but I'd be interested to hear if somebody can suggest a best practice in this area.

Having said that, non-random salts (such as a numeric PK) are still a lot better than just a straight hash. This at least forces the attacker to create a new rainbow table for each user he wants to attack instead of being able to rely on a single generic rainbow table.
By Willie Wheeler on Sep 1, 2008 at 10:02 PM PDT
I did enjoy this article but perhaps it would better be entitled Storing Password Hashes Securely as you are in fact storing hashes and not passwords.

There are some situations which require storing passwords themselves. This is a very difficult problem I would love to see more written about.
By Richard Minerich on Sep 2, 2008 at 7:02 AM PDT
Hi Richard. I can see what you are saying. I agree that in some cases you want to store passwords themselves (or at least encrypted passwords that you can decrypt). That can happen for example if you need to use the password to authenticate into some other system. In that case you might consider using an actual cipher (two-way) to encrypt the password before storage instead of a hash function (one-way).
By Willie Wheeler on Sep 2, 2008 at 7:26 AM PDT
Nice article Willie!!! Can you share some best practices to implement "remember me" functionality? Do you think using a "salted hash" is a good enough solution to store passwords in cookies?
By Venugopal on Sep 2, 2008 at 8:48 AM PDT
Excellent article describing a subject that can be difficult for people to get there heads around.
Do you have any more advice about choosing a salt? Would you create a random string and store it with the user?
By Ben on Sep 2, 2008 at 9:33 AM PDT
Great article Willie. You've opened by eyes to the random salt concept. Thanks, Collin
By Collin on Sep 2, 2008 at 10:19 AM PDT
@Venu: Regarding remember-me, one suggestion would be to recognize the reality that it trades security for usability. It's really authenticating the browser (using a persistent cookie) instead of the user, which is sometimes OK and sometimes not. (For example, several users in the household can share a machine; several users may share a public machine.) So I would suggest that when someone remember-me's into your app, the safest assumption is to assume that the user is very possibly *not* the user who they appear to be. This assumption forces you to distinguish high- and low-risk functionality, and if the user attempts something high-risk, you force an actual login. Amazon does exactly this. A remember-me user can see product recommendations, but if he wants to buy something he has to log in.

For the actual mechanics (for instance, what tokens to use), there are multiple approaches. Here are two you might take a look at:

http://static.springframework.org/spring-security/site/apidocs/
org/springframework/security/ui/rememberme/TokenBasedRememberMeServices.html

and

http://static.springframework.org/spring-security/site/apidocs/
org/springframework/security/ui/rememberme/PersistentTokenBasedRememberMeServices.html

The first doesn't require a database, but it does involve storing the username in the cookie, which may be unacceptable in certain cases. (For example, if you are doing remember-me for a credit repair website, you may not want to expose usernames in cookies.) The second does require a database but it avoids the username problem. It is based on the article

http://jaspan.com/improved_persistent_login_cookie_best_practice

Hope that helps.
By Willie Wheeler on Sep 2, 2008 at 9:16 PM PDT
@Ben: See my response to Aaron, but I'll elaborate.

One approach is to use randomization to create secret salts. That makes brute forcing the hash orders of magnitude harder because your salt search space is now orders of magnitude larger. But this only works if the salts can be kept secret. If the attacker has the per-user salts (which seems likely if he already has the password database) then brute-forcing a hash with a random salt is no different than brute-forcing a hash with a nonrandom salt--one the salt is revealed, it makes no difference whether the salt is random or not. The salt is known; the search is over. :-)

If you can keep the salt(s) secret (either global salt or per-user, however you decide to do it), then your passwords are much more secure, since it's essentially like having two passwords, with at least one of them being very strong. But now you just have to figure out how you're going to manage to keep the salts secret. That is a challenge in its own right.

The other approach is to treat the salts as known rather than secrets. Though it's easier to crack this scheme, this approach is still useful because it foils attempts to use a precomputed rainbow table against your passwords. The attacker can still get at your passwords by building new rainbow tables, but now he has to work at it. :-) You're essentially creating a deterrent that will cause many attackers to look elsewhere, and such deterrents are very much a tool you can use to enhance security.
By Willie Wheeler on Sep 2, 2008 at 9:57 PM PDT
Just one more thought regarding the deterrent thing I just mentioned. I was at a security talk the other day and the presenter noted that attackers are very much ROI-driven. Deterrence adds security because it drives down the ROI.
By Willie Wheeler on Sep 2, 2008 at 10:12 PM PDT
when will your book Spring in practice come in Indian market ?
By punit singh on Nov 15, 2008 at 2:41 AM PST
@punit: Thanks for asking. I'm not sure how Manning handles international sales, so I can't speak to the Indian market. In terms of the book itself being available, the original estimate was June 2009, but I suspect that we will push that back a bit since the original schedule didn't account for Spring 3, and we obviously want to cover Spring 3.
By Willie Wheeler on Nov 17, 2008 at 1:10 AM PST

Post a comment

Your name:
Your e-mail address (won't be displayed):
Your web site (optional):
example: www.xyz.com
Your comment:
Preview:
By You
Please help us reduce comment spam:
Spring in Practice
My brother and I are writing Spring in Practice for Manning!

What's New?

2009-08-30 - Check out my two-part series on DZone: Spring Integration: A Hands-On Tutorial.
2009-03-25 - My new article Getting Started with Spring Batch 2.0 is available on DZone.
Home | Consulting | Tech Articles | Mailing List | Contact | Spring Blog
Copyright © 2008 Wheeler Software, LLC.