How not to store user passwords

Published in: HowTo, Security

If you are running a Web App and you are storing user passwords, it is very easy to get things horribly wrong, it’s better to use third-party sign-in services like Facebook, Twitter or Google. In my experience, I have seen a lot of Web-Apps and Services going this route, not because they are lazy – but because they are offloading an aspect of your app that is incredibly difficult to get it right and secure. In today’s world of high-profile hacking of user password, it’s probably the best thing you can do for your users. Even large companies with well-funded security teams often get things horribly wrong.

But let’s say your app has become incredibly popular, with 1000s of signups per day. There is a point in your business where your user base is large enough for you to start feeling uncomfortable at becoming reliant on third-party sign-in services. At that point, assuming you have the know-how and resources to implement a proper and secure user password storage system, it’s probably not a bad idea to move to your own self-hosted system.

Because it is easy to get things wrong and how often we make this elementary mistakes in the wild, I am going to list three ways NOT to store password.

1. Don’t store user passwords.

The most basic password storage system is to just implement backend database where username and passwords are stored in plaintext. I am not kidding, this is done so often and it is still so common on the web its not even funny. Even today, in the year 2018, you see websites storing passwords in plaintext – you can verify this when trying to recover your password by email, they simply email back your password in plaintext. It’s a huge red flag if you see any websites doing this – stop using their service as soon as possible, or if you must use their service, make sure you are using a unique password. Chances are high that your password is as bad as gone. Because if any website is lazy enough to save your password like this, who knows what other unholy things they are doing security-wise. I once found out my bank was storing the password in plaintext, needless to say, I closed my online banking account. I only used checks or debit-card. You have no business storing your user password in your database.

2. Don’t encrypt user passwords.

The obvious next step would be to implement some kind of encryption when storing a password in the database, better than the previous method, but still, a very bad way to store user password.

This rudimentary encryption process works like this, you take user password, and you use a key to encrypt it and store it in your database, the key itself is also stored in the database. The problem with this approach is that if your server or database is compromised, it happens more often than you might think, the user is one step away from decrypting your database, thanks to you the key is already there.

This approach is surprisingly common among developers because it’s an easy compromise between “Secure” and plaintext password.

3. Don’t Hash your passwords.

Password hashing is a form of a fingerprint of your password, in this method, you don’t actually store any password in the database, you store the fingerprint (Hash) of the password, so when user tries to sign in to their account you app creates a hash of the password and looks up the hash in the database to see if they match and that’s how your access is verified. This method is much better than previous 2 methods discussed but has some serious flaws if not implemented properly.

First of all, there are many many hashing algorithms out there, some are more secure than others, discussing the pros and cons of hashing algorithms are outside the scope of this article, to minimize the scope of hashing algorithm research, the current industry standard (2018) in terms of safety and difficulty in brute-force and other types of attack, the top three choices are PBKDF2, bcrypt, and scrypt. You should definitely do your own research.

The reason not to rely on Hashing your password, because most people goes with more widely known and less secure hashing algorithms, like MD5, SHA (1, 2, 3). The reason developers go with MD5 and SHA because they are well known and easier to implement and also because it’s less CPU intensive compared to bcrypt and scrypt. Higher computational cost with hashing algorithm also means higher cost of developers, MD5 is many order of magnitude faster to brute force on the same password than scrypt. Which means when you have a large number of users your password lookup on similar hardware will be lower for scrypt. Meaning you will have to invest more in hardware. Which is why some developers generally try to avoid more complexity, but it also makes you vulnerable to Brute-Force, Lookup Tables, Reverse Lookup Tables and Rainbow Tables attacks. Having a poorly implemented hashing is as bad as not having any form of hashing at all.

So What is the best industry practice when trying to store user passwords in the database?

The best approach is a mixture of Hashing + Salting + enforcing mandatory strong password (lowercase letters, uppercase letters, numerals, and special characters with at least 10-12 characters long) + Database server not directly accessible from the internet, preferably on a different server from your web application.

Salting passwords work by adding random strings to password and then hashing it, this means no two same passwords should have the same hash, this along with previously mentioned best practices makes it close to impossible (or very very very time consuming and difficult) to crack a single password, let alone millions of passwords.

If you follow the above-mentioned rule of best password storage practice, you can store your password on the database without encrypting it, because it adds such a high difficulty level. But encrypting the database itself, even if its hashed and salted is not a bad idea. But the important part is to add a process and policy to store your encryption key in a way that it makes it very difficult to infiltrate your database. Which obviously adds a lot more complexity to an already complex password storage system.

Which is why I recommend everyone, if they are starting out and not very experienced with password management and storage system in a secure way, it’s best to offload this to a third party login system.


about | twitter | facebook | archive | rss