What is the point of using a salt when encrypting passwords in a web application?
August 26, 2006 12:05 PM Subscribe
What is the point of using a salt when encrypting passwords in a web application?
I've lately seen a lot of recommendations in the web app world to add a random salt to users' passwords before encrypting them (MD5 or similar). The salt is then stored in the database along with the encrypted password. People talk about this as if it adds a major extra layer of security, but I can't understand the benefit of it.
I can understand the benefit of doing this in a situation where the encrypted passwords are easily accessible (such as the traditional UNIX passwd file). Without a salt, the attacker can take the list of encrypted passwords and run a pre-encrypted dictionary against them quickly and easily.
But if you're trying to crack a login page on a web app, your two options are basically to either do a brute force dictionary attack against the login page itself, or somehow get hold of the (encrypted) password table.
In the first case, it doesn't matter what encryption or salting you've got going on behind the scenes, since your attacker is just firing normal plain text passwords at your login form. So salting doesn't help security here, does it?
And in the second case, if you've hacked the server to the extent that you're able to read a table of encrypted user passwords from the database, don't you have about as much access as you're ever going to need? Why not just read the other tables in the database to gain access to the confidential information? Why bother trying to crack the passwords? I suppose it would make sense if you were storing user credentials in one database and user data in another database, but this doesn't seem to happen often.
What am I missing? Why bother doing this?
I've lately seen a lot of recommendations in the web app world to add a random salt to users' passwords before encrypting them (MD5 or similar). The salt is then stored in the database along with the encrypted password. People talk about this as if it adds a major extra layer of security, but I can't understand the benefit of it.
I can understand the benefit of doing this in a situation where the encrypted passwords are easily accessible (such as the traditional UNIX passwd file). Without a salt, the attacker can take the list of encrypted passwords and run a pre-encrypted dictionary against them quickly and easily.
But if you're trying to crack a login page on a web app, your two options are basically to either do a brute force dictionary attack against the login page itself, or somehow get hold of the (encrypted) password table.
In the first case, it doesn't matter what encryption or salting you've got going on behind the scenes, since your attacker is just firing normal plain text passwords at your login form. So salting doesn't help security here, does it?
And in the second case, if you've hacked the server to the extent that you're able to read a table of encrypted user passwords from the database, don't you have about as much access as you're ever going to need? Why not just read the other tables in the database to gain access to the confidential information? Why bother trying to crack the passwords? I suppose it would make sense if you were storing user credentials in one database and user data in another database, but this doesn't seem to happen often.
What am I missing? Why bother doing this?
Are you sure the salt is added to the database? My understanding is that you use salt when transmitting the password so that it's harder to extract the password from sniffed packets and simply running the data against an MD5 database to get the decrypted info. You can read a lot about it here.
posted by furtive at 12:39 PM on August 26, 2006
posted by furtive at 12:39 PM on August 26, 2006
It's for if your database becomes compromised. Otherwise, why not just store plaintext passwords?
posted by trevyn at 12:48 PM on August 26, 2006
posted by trevyn at 12:48 PM on August 26, 2006
furtive has a good point.
Though, in response to your second case, I offer two reasons to add additional security to database tables: when the hacker has a limited time frame to rummage around, and just steals the password table to work on off-line; when the hacker wants to access the password-protected data through a legitimate "front door" for strategic purposes. In either case, you want to make decrypting passwords harder — regardless of the vulnerability of the system as a hole, post-compromise.
posted by silusGROK at 12:59 PM on August 26, 2006
Though, in response to your second case, I offer two reasons to add additional security to database tables: when the hacker has a limited time frame to rummage around, and just steals the password table to work on off-line; when the hacker wants to access the password-protected data through a legitimate "front door" for strategic purposes. In either case, you want to make decrypting passwords harder — regardless of the vulnerability of the system as a hole, post-compromise.
posted by silusGROK at 12:59 PM on August 26, 2006
Its basically a service to your users that, as you've suggested, provides little practical benefit to you. People tend to use the same passwords for many services; if an attacker is able to run a dictionary attack against a collection of usernames and passwords, he may be able to associate a specific password with a specific human being, and use that to impersonate the user at other sites.
posted by gsteff at 1:08 PM on August 26, 2006
posted by gsteff at 1:08 PM on August 26, 2006
Response by poster: Are you sure the salt is added to the database?
I'm pretty certain it is, otherwise there's no way to re-encrypt and hence check people's passwords when they're logging in. This is about the security of storing passwords, not the security of transmitting them.
posted by chrismear at 1:24 PM on August 26, 2006
I'm pretty certain it is, otherwise there's no way to re-encrypt and hence check people's passwords when they're logging in. This is about the security of storing passwords, not the security of transmitting them.
posted by chrismear at 1:24 PM on August 26, 2006
It's a mitigating factor against dictionary/brute force attacks.
Your assumption that that every attacker who gets access to the database also has access to the code is where your second scenerio breaks with reality. Attackers may exploit a vulnerability in the db server, or perhaps they get ahold of some db backups, or come across some other technique that gives them access to the user table.
Since you're worried about security you lock out accounts in your web app after n bad login attempts, so they can't use a dictionary attack on your application. But if they get access to your user table and you didn't salt your hashed passwords, they can use a dictionary attack to break many passwords.
Of course if you store the salt in the database, there's no real point to it.
Security is largely about making sure things fail well. In this case, a failure to protect your database doesn't also become a failure to protect your users' passwords.
posted by revgeorge at 1:29 PM on August 26, 2006
Your assumption that that every attacker who gets access to the database also has access to the code is where your second scenerio breaks with reality. Attackers may exploit a vulnerability in the db server, or perhaps they get ahold of some db backups, or come across some other technique that gives them access to the user table.
Since you're worried about security you lock out accounts in your web app after n bad login attempts, so they can't use a dictionary attack on your application. But if they get access to your user table and you didn't salt your hashed passwords, they can use a dictionary attack to break many passwords.
Of course if you store the salt in the database, there's no real point to it.
Security is largely about making sure things fail well. In this case, a failure to protect your database doesn't also become a failure to protect your users' passwords.
posted by revgeorge at 1:29 PM on August 26, 2006
Best answer: Great question. A lot of factual issues with the answers so far, though.
Storing plaintext passwords in a table is a horrible idea, for the main reason that it increases the benefit to any intruder. Once they bypass your security with an SQL injection attack (or, more likely, an attack you've never heard of) they then have a list of your users' names, email addresses, and passwords. As gsteff points out, they can then try those usernames and passwords on other sites, such as webmail, online banking, eBay, PayPal, etc. By storing your passwords in the clear, you are making the cost of any intrusion catastrophic. If you're building a web application, it's best to think about layered security, not "well, if they get past my web server they may as well have all the data for the business."
Hashing the password is a step up, but without a salt it allows for a type of attack called a rainbow attack, in which the attacker precomputes (or these days, just downloads) a table of the MD5 hashes for all strings of a certain size with a certain character set. For example, an attacker could have a rainbow table for all passwords 1-12 characters long with letters, numbers, and special characters. With this kind of table, turning an MD5 hash into a usable password becomes a
Adding a salt to the password (
A salt is not a secret value and is usually kept along with the salted hash in the database. If you don't have the salt, you cannot reconstruct the salted hash given a possibly valid password:
Finally, salts do not provide protection against dictionary attacks or brute force attacks. The computational overhead of including a public salt along with a candidate password from a dictionary or brute force algorithm is trivial. There is no protection against brute force attacks besides increasing their computational expense beyond your attackers' means.
Please please please please go buy a copy of Practical Cryptography, by Niels Ferguson and Bruce Schneier. If you're writing an authentication system, you absolutely must know what you're doing. Otherwise you will turn a bad situation (hacker breaks in) into a nightmare (hacker breaks in, steals user table, recovers passwords for your customers, sells the information on the black market, etc.).
posted by Coda at 1:42 PM on August 26, 2006 [8 favorites]
Storing plaintext passwords in a table is a horrible idea, for the main reason that it increases the benefit to any intruder. Once they bypass your security with an SQL injection attack (or, more likely, an attack you've never heard of) they then have a list of your users' names, email addresses, and passwords. As gsteff points out, they can then try those usernames and passwords on other sites, such as webmail, online banking, eBay, PayPal, etc. By storing your passwords in the clear, you are making the cost of any intrusion catastrophic. If you're building a web application, it's best to think about layered security, not "well, if they get past my web server they may as well have all the data for the business."
Hashing the password is a step up, but without a salt it allows for a type of attack called a rainbow attack, in which the attacker precomputes (or these days, just downloads) a table of the MD5 hashes for all strings of a certain size with a certain character set. For example, an attacker could have a rainbow table for all passwords 1-12 characters long with letters, numbers, and special characters. With this kind of table, turning an MD5 hash into a usable password becomes a
O(n)
operation taking a minute or two on commodity hardware. An entire user database with plain MD5 hashes can be converted into a list of usable username/password pairs in a matter of hours on an average workstation.Adding a salt to the password (
h(salt + password)
) means that the attack must effectively have a specific rainbow table for each salt. If your salt size is long enough (and it doesn't take much--yay exponentiation) you can effectively push the computational and storage requirements for a rainbow attack outside of your attackers' means.A salt is not a secret value and is usually kept along with the salted hash in the database. If you don't have the salt, you cannot reconstruct the salted hash given a possibly valid password:
h(salt + password) == h(?? + candidate_password)
doesn't work. Furtive, you're thinking of salts in challenge-response protocols, which is a totally different situation.Finally, salts do not provide protection against dictionary attacks or brute force attacks. The computational overhead of including a public salt along with a candidate password from a dictionary or brute force algorithm is trivial. There is no protection against brute force attacks besides increasing their computational expense beyond your attackers' means.
Please please please please go buy a copy of Practical Cryptography, by Niels Ferguson and Bruce Schneier. If you're writing an authentication system, you absolutely must know what you're doing. Otherwise you will turn a bad situation (hacker breaks in) into a nightmare (hacker breaks in, steals user table, recovers passwords for your customers, sells the information on the black market, etc.).
posted by Coda at 1:42 PM on August 26, 2006 [8 favorites]
"I've lately seen a lot of recommendations in the web app world to add a random salt to users' passwords before encrypting them"
Generally, if a lot of people, some of them experts, are suggesting something that's trivially easy to do, you need a compelling good reason to do otherwise.
"And in the second case, if you've hacked the server to the extent that you're able to read a table of encrypted user passwords from the database, don't you have about as much access as you're ever going to need? "
Understand that a salt is more than encryption; it's one way. If I learn a salted password, it's impossible to get (a single) original password from it.
Consider that many users (hi mom!) use the same login name and password for all sites. If a hacker gains access to your system sufficient to read salted passwords, yes, he may have complete access to your system.
If the case of my mom, if your system records only salted passwords, all the hacker has is access to your system.
But if your system doesn't use salted password, the hacker now has access to my mom's eBay and PayPal accounts and her email, too.
So be good to the users who have trusted your system enough to register; don't allow a security failure at your site to compromise their accounts at other sites.
posted by orthogonality at 1:45 PM on August 26, 2006
Generally, if a lot of people, some of them experts, are suggesting something that's trivially easy to do, you need a compelling good reason to do otherwise.
"And in the second case, if you've hacked the server to the extent that you're able to read a table of encrypted user passwords from the database, don't you have about as much access as you're ever going to need? "
Understand that a salt is more than encryption; it's one way. If I learn a salted password, it's impossible to get (a single) original password from it.
Consider that many users (hi mom!) use the same login name and password for all sites. If a hacker gains access to your system sufficient to read salted passwords, yes, he may have complete access to your system.
If the case of my mom, if your system records only salted passwords, all the hacker has is access to your system.
But if your system doesn't use salted password, the hacker now has access to my mom's eBay and PayPal accounts and her email, too.
So be good to the users who have trusted your system enough to register; don't allow a security failure at your site to compromise their accounts at other sites.
posted by orthogonality at 1:45 PM on August 26, 2006
One other salt-related note for web applications.
You'll probably need to use cookies to save authentication information on your client's computers so you can recognize them. Salt's are critical in producing cookies that you can later validate. The basic strategy goes like this:
Decide what pieces of data you want stored about a given user, like their userid, user name, whatever. Also store, in clear text, the date that the cookie should expire. separate each of those fields with some character, so your string in the clear might be "1$heresiarch$somemachinereadabledate". Now take that string, add the delimiter and the salt, and then tack it on the end, so you get "1$heresiarch$somemachinereadabledate$hash(clear text fields + salt)". Now, when a client hands you back this cookie you just run the process in reverse. Look at the data in the clear, add the salt to it on the server side and rehash it. If it matches the cookie hash, then you know the cookie was issued by you and the data included in it is valid. By including the date, you can also enforce cookie expiration in case the user agent misbehaves. If someone tries to mess with the cookie, the hashes won't match, so you're all set. If you didn't use a salt here, this process wouldn't work at all, because anyone could produce a valid cookie on their own.
This is pulled more or less verbatim from this paper, which is quite good, but a little obtuse. I ran across it when trying to figure out how to do the cookie thing correctly for an app of my own, and their solution seems rock solid to me.
Ditto on the factual issues Coda points out. Be very careful in this territory. It's easy to go catastrophically wrong.
posted by heresiarch at 2:00 PM on August 26, 2006 [1 favorite]
You'll probably need to use cookies to save authentication information on your client's computers so you can recognize them. Salt's are critical in producing cookies that you can later validate. The basic strategy goes like this:
Decide what pieces of data you want stored about a given user, like their userid, user name, whatever. Also store, in clear text, the date that the cookie should expire. separate each of those fields with some character, so your string in the clear might be "1$heresiarch$somemachinereadabledate". Now take that string, add the delimiter and the salt, and then tack it on the end, so you get "1$heresiarch$somemachinereadabledate$hash(clear text fields + salt)". Now, when a client hands you back this cookie you just run the process in reverse. Look at the data in the clear, add the salt to it on the server side and rehash it. If it matches the cookie hash, then you know the cookie was issued by you and the data included in it is valid. By including the date, you can also enforce cookie expiration in case the user agent misbehaves. If someone tries to mess with the cookie, the hashes won't match, so you're all set. If you didn't use a salt here, this process wouldn't work at all, because anyone could produce a valid cookie on their own.
This is pulled more or less verbatim from this paper, which is quite good, but a little obtuse. I ran across it when trying to figure out how to do the cookie thing correctly for an app of my own, and their solution seems rock solid to me.
Ditto on the factual issues Coda points out. Be very careful in this territory. It's easy to go catastrophically wrong.
posted by heresiarch at 2:00 PM on August 26, 2006 [1 favorite]
Also note that salted passwords make it impossible for unscrupulous employees and contractors to misuse users' passwords. It being impossible, that in turn makes it far easier for you to absolve your company when a user's account somewhere else is hacked, or to assure everyone that the damage is limited when somebody buys your old server hard drive and recovers the database and password list.
posted by orthogonality at 2:06 PM on August 26, 2006
posted by orthogonality at 2:06 PM on August 26, 2006
Response by poster: Thanks for the fantastic answers, everyone.
Just to reassure you, I am already using salted passwords, and I did understand the essential reasoning behind them. I was just intrigued by the way I'd seen salting presented recently almost as a kind of magic bullet for highly increased app security, and I couldn't see why that would be the case, particularly in simple single-database web apps.
Now that I've seen some well-argued reasons for doing it, it makes a lot more sense. And it's got me thinking about some other security issues, like heresiarch's cookie strategy.
posted by chrismear at 2:19 PM on August 26, 2006
Just to reassure you, I am already using salted passwords, and I did understand the essential reasoning behind them. I was just intrigued by the way I'd seen salting presented recently almost as a kind of magic bullet for highly increased app security, and I couldn't see why that would be the case, particularly in simple single-database web apps.
Now that I've seen some well-argued reasons for doing it, it makes a lot more sense. And it's got me thinking about some other security issues, like heresiarch's cookie strategy.
posted by chrismear at 2:19 PM on August 26, 2006
In slightly simpler terms, the answer to the question is exactly the same as the answer to "why encrypt at all to begin with?" If you don't use salts, then an attacker only has to generate a whole bunch of md5s (or whatever) once, and they'll be good for unencrypting any DB they come across. Worse, if other sites also neglect to use salts, they can just take those md5s and use them in cookies, bypassing the need to know the password at all in many cases.
I realise this has pretty much been said, but I thought it would benefit from being re-stated in a single paragraph.
posted by reklaw at 2:30 PM on August 26, 2006
I realise this has pretty much been said, but I thought it would benefit from being re-stated in a single paragraph.
posted by reklaw at 2:30 PM on August 26, 2006
So since MD5 has been broken, is anyone advocated going to a newer hashing algorithm that hasn't been broken. From a quick look at wikipedia, I see that SHA-1 has also been attacked, so researchers are worried about subsequent algorithms that build on that.
Maybe its just a case of "well, whatever we use will be cracked eventually, so we might as well use a standard MD5 with salt instead of a strong base algorithm" ?
posted by rsanheim at 10:33 PM on August 26, 2006
Maybe its just a case of "well, whatever we use will be cracked eventually, so we might as well use a standard MD5 with salt instead of a strong base algorithm" ?
posted by rsanheim at 10:33 PM on August 26, 2006
rsanheim: Adding a salt does not strengthen the hash algorithm for any other attack besides rainbow attacks. Neither MD5 nor SHA-1 have been attacked in ways which would be useful for attacking web applications (most of the repercussions deal with digital signatures), so many people have, for lack of good libraries in their development platform, continued using MD5 and SHA-1, since they're nearly ubiquitous these days.
That said, I'd advise anyone building a system now to use SHA2 as a hash algorithm.
Since I'm nitpicking, it's also better to use a strong HMAC construction when hashing two strings together. It's not hard to implement, and is the appropriate cryptographic primitive for hashing multiple strings together securely.
posted by Coda at 3:21 PM on August 27, 2006
That said, I'd advise anyone building a system now to use SHA2 as a hash algorithm.
Since I'm nitpicking, it's also better to use a strong HMAC construction when hashing two strings together. It's not hard to implement, and is the appropriate cryptographic primitive for hashing multiple strings together securely.
posted by Coda at 3:21 PM on August 27, 2006
This thread is closed to new comments.
In non-critical systems, this is the only argument you need. Storing plaintext passwords is no real problem if having access to the database is enough to compromise the whole system.
posted by wackybrit at 12:37 PM on August 26, 2006