Hacking authentication systems

Password Storage 101


Can you keep a secret?

By Kurt Seifried

If there's one thing that hasn't changed a whole lot in computer security, it's how we authenticate things. Your basic choices are: something you are (biometrics), something you have (a time-based password token), and something you know (e.g., a password or passphrase).

Something you have doesn't work very well because you need a secure biometric reader on the remote end. The number of users with one of these is basically zero. Time-based tokens cost money, have to be shipped to a user, and have to be carried around. (I have five RSA tokens on a separate keychain. No more, please!) Neither of these two methods works if it's a computer, not a human, that needs to authenticate to something.

This pretty much leaves passwords, which pose two problems: you have to authenticate to something and something has to authenticate to you.

Authenticating to Something

One of the hardest things to do securely is authenticate to something because, unless you make a user type in the password each time the program is run, you have to store the credentials somewhere the program can get them. So what can be done to protect them? The traditional method is to encrypt the password; however, to decrypt it you need a ... well, a password. So you're back where you started, but with one advantage, the real password is protected should an attacker manage to copy it off the system.

But this system of protection does you no good if the program must run without human intervention (e.g., the database password used by a PHP web application that is run every time a request is served), as evidenced by the attacks against Network Solutions customers that compromised WordPress blogs by accessing the back-end databases using the password saved in the WordPress configuration file, which was readable by other users on the same server.

The best (and about only) way to protect passwords stored for automated use is to apply strict file permissions that do not allow other users to access the file. If you're lucky, the program can start running with elevated privileges and then drop them, allowing you to restrict access to the configuration file to a specific user that isn't used for anything else. However, this generally won't be available for web apps and related programs.

For local desktop applications that need to authenticate to a remote server (e.g., an email client or backup program), you can use system key storage, like Gnome Keyring [1] or KDE KWallet [2]. You authenticate to the key storage, then the Keyring/KWallet provides access to stored credentials and passwords for programs that need them. Of course, this doesn't help for unattended applications that aren't running on a desktop.

Providing Authentication

The flip side is providing authentication services. Unless it's a public read-only service, chances are users will have to register in some form and authenticate to prevent abuse/spammers/attacks/etc.

In order of least secure to most secure are: storing passwords in cleartext, storing one-way hashes of a password, storing a one-way hash of the password plus a salt value, and using an external (and hopefully secure) authentication service (e.g., LDAP, Kerberos, OpenID).

Cleartext Passwords. Unbelievably, some software still stores the user's original password in an unprotected format. An attacker that gains access to the system could copy and use these credentials, which is especially dangerous because many users use the same password for multiple sites and services. About the only justification for storing a plaintext password is so you can tell the user what it is if they forget. So, if a provider is able to retrieve your password for you, that means an attacker can, too.

One-Way Hashed Passwords. Like French fries, this technique is largely wasted if you don't use any salt. A one-way hash, even a strong one such as SHA512, still allows an attacker to launch dictionary attacks against the hashed password. Any weak passwords will be found, and if the attacker has access to enough computational power (e.g., EC2 or a botnet) [3], a lookup service with pre-computed values [4] or rainbow tables (partially computed one-way hashes) [5], the password is relatively easy to retrieve. With the availability of solid-state disks, these lookup tables can be accessed faster than ever, making it ever easier for attackers.

A recent attack against the Apache Software Foundation shows why a one-way password hash is such a bad idea. A cross-site scripting (XSS) vulnerability was used in the JIRA issue tracking software. Using it, the attacker stole login credentials to an administrative account, which was then used to copy the password file (which was hashed using SHA-512 but without a salt value), further compromising the system [6]. The end result was that all users had to change their passwords, especially if they use the same password at other sites.

One-Way Hash with Salt. This is the current gold standard for password storage. You take the password and hash it using a one-way function (such as Crypt, SHA512, etc.) with a random salt value. Note that the UNIX crypt command has been doing this since the 1970s. The three main aspects to the salt value are: its length (longer is better), where the value is stored (as far away from the password database and as securely as possible), and whether to use the same value for all passwords or generate new salt values (daily, for every password, etc.). Although you can use more than one salt value, unless each is stored in a separate method, it won't be any harder for the attacker to steal one or a dozen. Virtually every programming language that has a hash() function supports a salt value. If you find one that doesn't support salt values, I'd love to know!

Authentication Services. One way to handle authentication securely is to remove the back-end functions of username and password storage from your application and use an authentication service such as LDAP or Kerberos. These systems also have the advantage of scaling and providing authentication services to a large number of applications. The downside is if you have to set up and maintain these systems, which typically are significantly more complicated than the built-in authentication.

Outsourcing Authentication

I never thought I'd say this but: You can outsource your authentication, and it might prove more secure than doing it yourself. Depending on whether you need simply to authenticate users so they can receive personalized services (e.g., setting preferences or remembering what documents they created) or to verify that Bob Smith is indeed the Bob Smith that works on the fourth floor in accounting, you have some options.

One of the most popular and publicly available authentication systems is OpenID [7]. OpenID allows users to get an OpenID account from a number of providers (WordPress, Yahoo!, AOL, and VeriSign, to name a few), which can then be used with any application that supports OpenID. This also has the advantage of not requiring users to create yet another account for a site they might use only occasionally. Once they have an OpenID, they are good to go. (With sites like StackOverflow and WordPress using OpenID, most geeks have one.) However, for non-savvy users, OpenID probably has a few too many steps (choose an OpenID provider, set up an account, go back to the site you wanted to log in to, and allow it to use your OpenID).

Conclusion

Of course, none of this matters much if your users pick bad passwords or you have software that doesn't limit the number of bad logins (a.k.a. password-guessing attempts). However, if you don't store passwords securely, it doesn't really matter what users do. Long-term, we're going to have to figure out something better than passwords. A recent article talked about pacemakers and other medical devices that support wireless communication and external control that are password protected. The problem with this being: How do you get the password from someone who is hurt or unconscious (or has Alzheimer's and forgot what it is). The solution proposed so far is to tattoo the password onto the person. (Good thing the medical devices don't have a mandatory 30-day password change policy!)

Hopefully we can do better.

INFO
[1] Gnome Keyring: http://live.gnome.org/GnomeKeyring
[2] KDE KWallet: http://docs.kde.org/development/en/kdeutils/kwallet/
[3] "Amazon's EC3 brings new might to password cracking" by Dan Goodin. "The Register", November 2, 2009, http://www.theregister.co.uk/2009/11/02/amazon_cloud_password_cracking/
[4] SHA1 lookup: http://www.sha1-lookup.com/
[5] Free Rainbow Tables: http://www.freerainbowtables.com/
[6] apache.org incident report: https://blogs.apache.org/infra/entry/apache_org_04_09_2010
[7] OpenID Foundation: http://openid.net/
THE AUTHOR

Kurt Seifried is an Information Security Consultant specializing in Linux and networks since 1996. He often wonders how it is that technology works on a large scale but often fails on a small scale.