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:
- Hash the unsalted password in the database (not secure).
- When displaying the login form, set a single-use token that is also included in the form.
- 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…
This post is part of the thread: Passwords – an ongoing story on this site. View the thread timeline for more context on this post.