Salting Passwords in DB or Across the Wire?

Posted in: Development

One of the sessions at SxSW talked about the importance of salting passwords in the database in case an attacker gains database access. The assertion is that hashing in the database is not enough, that the hash needs to be combined with salt. This got folks (including me) thinking and talking about this again, which is a Good Thing.

I completely understand and agree with this logic, and did a little poking around in my code to see if I could implement this before ran into a logical roadblock and remembered why I hadn’t in the first place. The approach I’m currently taking is to guard for security across the wire instead of security in the database.

Here is the approach I take:

  1. Hash the unsalted password in the database (not secure).
  2. When displaying the login form, set a single-use token that is also included in the form.
  3. Before submitting the username and password, hash the password once to match the database state, then again with the single-use token. This result is then passed along with the form to the server. I wipe out the user entered password so that the password the user knows about is never sent across the wire at all. Note that this requires JavaScript to be enabled in the browser.
  4. On the server pull the unsalted, hashed password from the database and hash it with the single-use token, then compare that to the hashed value received from the login form.

By using this approach the hashed password being submitted over the wire from the login form is never the same (even though the password is the same each time). This means that a man-in-the-middle attack (think public WiFi) is defeated as the login credentials that are passed are valid only for that session.

What it doesn’t solve is having unsalted hashed passwords in the database that are vulnerable to lookup via rainbow tables if an attacker gained database access. Of course, if one were to salt the hash in the database and pass the salt down to the login form so that it could be included in the browser-side hash generation, it would defeat the purpose of the (secret) salt in the first place.

The question I asked is: which is more likely, an attacker gaining access to the database or someone sniffing traffic on the wire.

I believe the wire attack is a more likely vulnerability. People will generally connect to any available WiFi network (especially with mobile devices), with little regard to security.

However, though the wire attack might be the more likely you could make the case that a compromised database is the more dangerous of the two situations, especially in the case that you have a large amount of user data stored in a single database. In that situation, it might be wise to prefer to guard against a wide user data compromise instead of the wire attack that would only compromise access for a single user.

I guess it comes down to each application’s specific use case.

Another solution to this might be a public/private key encryption solution, but admittedly I don’t know enough about this (yet) to know how feasible it would be to implement with a simple user password input model.

Have another method of handling this? Think I’m wrong about wire vs. database being a more likely attack scenario? Think there is an absolute here that I’m missing? State your case in the comments…

Popularity: 1% [?]

Posted March 19th, 2010 @ 10:59 AM

12 Replies

  1. Joe Hall adds this Comment:

    I agree that its more likely that attacker with hit over the wire versus the DB. But, If an attacker gets access to a DB they in theory probably have access to your salt formula and as a result could reverse engineer an attack with rainbow tables.

    March 19th, 2010 at 11:06 am

  2. Alex adds this Comment:

    True, I should have clarified this as a “database only” vulnerability. If an attacker gains access to both code and database, then salted passwords are subject to the same rainbow table lookups (albeit with an additional step in the process).

    That’s another good reason to optimize against a wire attack vs. a database only attack.

    March 19th, 2010 at 11:09 am

  3. Robert Accettura adds this Comment:

    IMHO wire attacks are much more worthwhile to protect against.

    The problem with database only, is that it seems rare only the DB is compromised. Normally it’s the last to be attacked, the web app being in front of the DB. The DB should be the most restricted (only the webapp needs to even communicate with it).

    That said, you can pretty much solve wire attacks by using SSL which also verifies identity and helps against MITM attacks. IMHO more worthwhile than a JS solution. Overhead is reduced if you have SSL hardware on your server.

    March 19th, 2010 at 11:19 am

  4. Alex adds this Comment:

    Agreed. SSL is a great tool in this mix, however my experience has been that few of my customers actually install and configure SSL when they install a web app. I want to do what I can to help in those cases as well.

    March 19th, 2010 at 11:32 am

  5. Dave Bacher adds this Comment:

    I think I’m missing something here. I thought salt was public information designed to increase the size of the required rainbow tables. The salting function is just the hashing function and it is designed to be one-way. So a) it doesn’t matter if the salt is exposed publicly, and b) if you have a good hashing function, it’s hard to reverse engineer the salting even if you know
    the function.

    Am I misinformed?

    March 19th, 2010 at 12:04 pm

  6. Alex adds this Comment:

    That’s interesting, I hadn’t heard it looked at that way. Wikipedia says:

    For best security, the salt value is kept secret, separate from the password database. This provides an advantage when a database is stolen, but the salt is not. To determine a password from a stolen hash, an attacker cannot simply try common passwords (such as English language words or names). Rather, they must calculate the hashes of random characters (at least for the portion of the input they know is the salt), which is much slower.

    In some protocols, the salt is transmitted as cleartext with the encrypted data, sometimes along with the number of iterations used in generating the key (for key strengthening).

    I think that a hash of a hashed string plus salt can make it harder to reverse, but once the algorithm is figured out it’s just layers.

    March 19th, 2010 at 2:23 pm

  7. Robert Accettura adds this Comment:

    Perhaps the best approach then is to check the protocol and require SSL for the app to run, unless the installer explicitly disables that check in the config file, in which case they assume the risk.

    Setting up a self-signed SSL cert, or buying and installing one (basic validation is only a few dollars now) isn’t a huge deal. Most just skip the step to speed and because it just works.

    Put a barrier there and people will second guess disabling a security feature.

    IMHO all apps should require SSL for login. I have an SSL cert for my blog for the purpose of securing the contact form, and for login (most important).

    March 19th, 2010 at 6:55 pm

  8. Alex adds this Comment:

    I think that would result in a lot of requests for refunds from my customers… ;)

    March 19th, 2010 at 7:11 pm

  9. Robert Accettura adds this Comment:

    I doubt it. If they are running it without https right now anyway, they obviously don’t care. Changing a config is hardly a barrier to adoption (is it really zero config right now?)

    March 20th, 2010 at 12:46 pm

  10. Joe Hildebrand adds this Comment:

    It looks like you’re trying to build DIGEST-MD5:

    http://tools.ietf.org/html/rfc2831

    however, that’s being replace with SCRAM:

    http://tools.ietf.or[...]asl-scram-11

    using one of these schemes that have been fully-vetted by the security community is a much better approach, even if you have to pull it up into your application rather doing inside the protocol like SASL imagines.

    March 22nd, 2010 at 1:06 am

  11. Otto adds this Comment:

    I’m not sure what you’re wanting is possible. There needs to be a shared secret of some kind in order for authentication to work at all.

    Basically, the client must send something that is what you store in the database, or which can be transformed into same through an algorithm.

    Now, since the function of that algorithm depends solely on inputs from the client and stored values already on the server, there’s no way to secure it if they know the values on the server or what the expected response is. All you can do is to make it difficult (take longer to brute force). You can’t actually make it impossible.

    March 23rd, 2010 at 10:51 am

  12. Kamasa adds this Comment:

    At least you have to use a salt for generating the hash. Otherwise the hash value is as “valuable” as the plain password when intercepted – at least on your site.

    June 2nd, 2010 at 12:46 pm

Add a Comment

Please note: Use of a non-personal web site or blog URL in the field below and/or comments that are off-topic, personal attacks, or support requests will likely be removed at my discretion. If you need help with WordPress or a WordPress plugin, please contact the WordPress HelpCenter.

Note: This post is over 5 months old. You may want to check later in this blog to see if there is new information relevant to your comment.

» «

About This Site

This is the personal web site of Alex King, a web developer in Denver, Colorado USA. More...


Crowd Favorite

Crowd Favorite is my software and web development business.

We build web applications, design and develop custom WordPress themes and plugins, and build custom sites using WordPress as a CMS.


Make Me Money

America - america09.com