No matter how good a password is, it provides little to no security if it is not stored and managed properly. Unfortunately, many online services have heinously-poor security practices. But that does not mean yours has to.
This week wraps up the password series with a look at what to do and what to avoid when developing systems that have to store and manage user credentials. If you are a software engineer and missed Part 1 or Part 2, you may want to read them first, even though they are not programming-oriented, in order to set the tone for why this post is important.
Avoid implementing poor password handling practices
As we did with password handling for users last week, let’s start with what to avoid when writing code to store and manage passwords.
- Do not store passwords in plain text. This one probably makes you think, “No, duh! Why would I store passwords as-is, with no protection at all?” However, a recent case of this was brought to light at Yahoo!. More specifically, a service that they acquired stored passwords in plain text and a SQL injection attack yielded the whole list. So, whether you are writing the code or inheriting it, this is still a valid issue to watch out for.
- Do not store encrypted passwords. When storing customer passwords in a database, encrypting them is not good enough. If you or your code can access the original passwords, someone else can too. There is no need to ever reconstruct the original password. More about this later in this post.
- Do not send passwords via email. Your customer just created an account and set their password. They do not need you to expose it via email, which is completely insecure. If they forgot their password and want to get it back from you, emailing it to them rather than providing a reset mechanism is a poor practice. It is likely that they use the same password on more than just your system.
- Do not make your own algorithms to secure passwords. Very few people on our planet have the skills, experience and expertise to create cryptographically-secure algorithms and methods. Unless you are one of them, use well-known, peer-reviewed solutions. Being peer-reviewed is especially important as demonstrated by the history of the formerly-classified SkipJack encryption algorithm, which researchers found to have significant vulnerabilities the day it was declassified by the US government.
- Do not restrict the length and type of characters for passwords. This is a classic warning sign that a system has poor password management. If, for example, your database’s password field is limited to 16 characters and you have to forbid the use of special characters such as # and ‘, you are unnecessarily crippling its security. Proper hashing eliminates these restrictions.
- Do not use security questions. Security questions that are intended to authenticate users reduce the security of systems. Answers to these kinds of questions are easily guessed or discovered via social networks or social engineering.
Best practices for storing and managing passwords
The methods for properly handling passwords are well known, but often overlooked, ignored or thought to be too much work to implement. You owe it to your company and your customers to do this correctly.
- Use a secure channel. When transmitting user names and passwords to/from your system use SSL/TLS to encrypt the data. This includes during login, changing passwords and resetting them. Ensure that the page on which the user enters their user name and password is clearly denoted as encrypted (e.g., the URL should be using HTTPS and identified as encrypted by the browser). I have seen many HTML forms submit a password via SSL, but the form itself appears on a non-encrypted page, which is misleading.
- Use a genuine SSL certificate. Self-signed certificates are not acceptable for customer-facing services. They trigger scary error messages in Web browsers and provide no means for protecting against a man-in-the-middle attack on your communication channel.
- Salt and hash passwords before storing them in a database. Hashing enables your system to accept passwords of any length and complexity, circumventing the need to filter them for characters with special meaning to databases. Defuse Cyber-Security has an excellent article describing, in detail, how to do this properly and includes example source code for PHP, Java, C# and Ruby. See Secure Salted Password Hashing – How to do it properly.
- Provide a mechanism to reset passwords. Notice that I did not say that you should provide a mechanism to recover passwords. If you properly salt and hash passwords, they should not be recoverable by anyone. Gmail and Amazon are examples of this kind of reset method. When implementing this, I would caution against giving an error message if a user’s name or email address is not found during the reset request. Doing so provides information to an attacker about which accounts are valid. Also, do not disable the account when a reset is requested. This could cause a denial-of-service condition since someone besides the account owner could have initiated the reset.
Further reading for the security-conscious
This series is by no means intended as the last word when it comes to password security. It is important to be diligent about staying up to date on security best practices and new vulnerabilities, especially if you are a software developer. Below are a number of good resources and I welcome your recommendations for additional ones. Just post them in the comments.
- Security Now video & audio podcasts: A weekly show on the twit.tv network about security news, in-depth discussions on security technologies and bi-weekly Q&A sessions.
- US-CERT Alerts: Notifications of security issues and vulnerabilities from the US Computer Emergency Readiness Team.
- @RISK Security Alert: Weekly newsletter from the SANS Institute with top security alerts and a full list of newly discovered vulnerabilities.
- The Open Web Application Security Project: A growing repository of information about security in Web applications, including the Top 10 Web Application Security Risks 2010 report (PDF).
- Secure Salted Password Hashing – How to do it properly: An in-depth guide to salting and hashing passwords.
- Statsprocessor – Why your password may never be safe again: High-speed Markov-based password guess generator.
- Whitepixel: Open source, GPU-based hash cracker.
- Inside Pro: More GPU-based cracking tools. Extreme GPU Bruteforcer works with up to 32 graphics cards.
- Hitachi ID Systems: Some password management best practices.
- A brief Sony password analysis: Findings from the passwords that were extracted from Sony’s databases.
- Google Authenticator: An inexpensive way to beef up account security in your software with one-time password, two-factor authentication.
- Google Authenticator Plugin: A simple way to add two-factor authentication to your WordPress blog.