Gaetan Lee
Photo credit: Gaetan Lee
del.icio.us Digg DZone Reddit StumbleUpon
1 | 2 | 3 | 4 | 5 | Next »
Security

Storing Passwords Securely

Use cryptographic techniques such as hash functions, salt and key stretching to store user passwords securely.

When dealing with user account information, there are lots of different security concerns that come up. Some examples include making sure users use strong passwords, preventing automated registrations, helping end users distinguish real sites from phishing sites, transmitting user data securely, and so forth—the list goes on and on.

In this article we're going to look at a specific piece of the overall user account security puzzle, and that's the problem of storing user passwords securely. Specifically we will see how you can use techniques from cryptography—hashing and salting your passwords—to make it harder for would-be attackers to uncover user passwords in the event that the password database (or password file, or whatever) is compromised.

We're only going to cover the concepts and techniques here; we won't get into how to actually implement this on any particular platform or using any particular framework. My brother John and I are currently writing a book for Manning Publications called Spring in Practice that will explain how to implement password salting and hashing using the Spring Framework, but for this article we'll just look at the concepts and techniques.

Also, a disclaimer is in order. I'm not a security expert of any kind, so if you are doing something requiring expert advice, please seek that out.

Why store user passwords securely?

It's worth thinking for a moment whether it's really even necessary to "store user passwords securely," if doing so involves anything more than limiting access to password data. If only a small number of trustworthy technical staffers have access to the user passwords, then why can't we just store the data in the clear? Doesn't that make it easier for technical staff to troubleshoot system issues (for example, admins can just log in as other users to try to reproduce errors), and doesn't that make it easier to help users recover forgotten passwords?

The answer to both of those questions is yes, but the story doesn't end there. The problem is that storing plaintext passwords also makes it easier for bad guys to see user passwords, and that's true whether bad guys break in from the outside or whether you have bad guys on your admin team. If attackers can log into your applications under somebody else's account, that's potentially very bad for you and your users. Moreover, because users often have the bad habit of reusing passwords (or else simple variants of passwords) across multiple applications and web sites, it's very difficult for you to limit the scope of the damage once somebody actually gets ahold of user passwords. The situation is possibly very damaging to your users and embarrassing to your organization. In all but the most trivial cases, it makes a lot of sense to store user data securely.

As an aside, note that in doing so, we don't give up the ability to allow admins or tech support reps to impersonate other users, nor do we sacrifice the ability to help users who have forgotten their passwords. We just have to use other techniques to accomplish those things, such as "run-as" impersonation, and using password resets in lieu of password recovery. Let's however stay focused on storing passwords securely.

So now we've seen why we don't want to store plaintext passwords. In the rest of this article we're going to look at four increasingly sophisticated cryptographic techniques for making it harder for attackers to get at your passwords. All four are based on something called a hash function, so let's start by talking about hash functions a bit.

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

Comments (14)

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

The Pandora pandora schmuck myth first Pandora Armreifenappears in lines Pandora Halsketten of Hesiod's poem in Pandora Charms epic meter, the Theogony (ca. 8th?7th centuries BC), without ever giving the woman a name. After humans Pandora Sets have received thethe myth is a rosetta stone kind of theodicy, addressing the question pop information, web easy get, sports fashion, news-fashionof why there is evil in the world. In the seventh hot-winter century BC, Hesiod, both in his Theogony (briefly, without naming Pandora outright rosetta stone language, rosetta stone spanish, abercrombie and fitch , Abercrombie Fitch

By pandora schmuck on Aug 30, 2010 at 11:15 PM PDT

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.