Fix your legacy password storage. NOW
Don’t put off fixing your legacy password storage problem
As the Yahoo breach shows, even well-established companies with massive resources and years of experience will put off fixing legacy security issues. The coverage on the Yahoo breach states that “most” of the passwords were bCrypted. This means some were not!
It can be daunting and difficult to upgrade a system’s password storage scheme. Hopefully you have only one component that authenticates users’ passwords and then hands off session credentials on behalf of users to your other systems. God forbid you have multiple disparate systems all authenticating user passwords individually. That can become a complicated mess and very expensive. However, it’s still worth it to make the effort to remediate. A breach of any kind can result in your user’s account data being sold off, plus a PR disaster. As bad as that is, it’s worse when the passwords are not hashed securely. Users often use the same password across multiple accounts so you’ve not only exposed them for your platform, but for others as well.
Getting Started
So, you’ve got user passwords saved weakly and you want to upgrade it so all users have bCrypted passwords with individual salts (Yes, there are some better hashing algorithms but this is an acceptable standard. Dropbox uses bCrypt so can you). Whatever the technical work required to upgrade your code to handle passwords better, you’ll eventually need to decide how to go about getting your users’ currently stored passwords upgraded to the bCrypt values.
Ironically, the best case scenario here is that the system is storing them in plaintext. Someone messed up real bad if this is the case, but now the fix is easy. Just run a script to bCrypt the passwords with individual salts and you’re good to go. Then go back and scrub all your db backups if you haven’t already. Because you haven’t changed anyone’s password, so any breach that gets your old data backups will still find the easily-crackable versions of the passwords.
But let’s say those passwords are not in plaintext. You’ve got the passwords hashed just not in a modern acceptable manner. Perhaps they are unsalted MD5 hashes (I’ve seen this way too many times to count…).
Your options:
- You can probably crack your own users passwords.
If the hash is something weak and without individual salts you can probably just rainbow table the passwords and get 99% of them in a relatively short period of time. (That’s what the bad guys are going to do). Then generate the new hash from these passwords and you’re good to go. Some product managers may have an issue with this. It just feels wrong to hack your own users’ passwords. Also this is only reasonable if you have a really weak hash. For moderately strong hashing, this will be a bit onerous. - Delete all the user passwords and make them reset next time they access the system.
Product managers hate this option with a passion. They will either laugh in your face or get sick at the thought if you suggest this. It’s well-known that users drop off at the slightest inconvenience. Forcing a password reset is also a strong warning signal to the savvy users that you messed up. From a security focus, this is the best and most effective option but you probably will not get buy off on this. - Use parallel password verification paths.
You’ll need to track which passwords have been updated and which have not. New users who create accounts will have their password stored correctly. Existing users who login with old passwords will get their current password updated to be stored correctly during login. Old users who are dormant and not using the system will STILL have the old unsafe passwords lying around in your system until they eventually return and login again. This is likely what Yahoo did, and thus the qualifier “most” when they are saying that “most” passwords were bCrypted. After a while you can probably convince your product managers to agree to invalidate all those dormant accounts’ passwords once they feel confident that their bread-and-butter users won’t be inconvenienced. These options leave something to be desired. This brings me to what I believe is the best and most painless option: - Hash the hash
Take all the badly hashed passwords and rehash them with bCrypt. Basically, all password hashing now takes two steps. First you hash the password using the old worthless hash and then you rehash that output with the new modern hashing process. The advantage here is that your existing users experience no hiccups on the upgrade. To be clear, there is NO security advantage to first hashing the password badly and then rehashing in a good way. This is purely to avoid inconveniencing your users.
Regardless, the update must happen
All these options are about how to upgrade your user’s saved password values to work properly with your new updated password hashing code. These options are all about balancing effectiveness with user experience. However, upgrading is really not optional. Your legacy password storage can’t go on. You should fix it now.