A Case For Standardizing Password Security
By Brian Neal
Copyright © 2012
In the past few years, we’ve seen an increasing number of attacks against online services, often resulting in theft of user databases. Concurrently, services themselves are multiplying with breakneck pace, from Facebook and Reddit to Farmville, Amazon, and e-trade, our social and financial lives are increasingly lived online.
And while this is an emerging community, it’s not that new and we’ve seen some unfortunate mishaps when it comes to security:
- Service frameworks are increasingly complex and difficult to secure – either due to insufficient testing and/or a lack of code audits
- Compromised services often result in the theft of poorly secured user databases
- Relatively few users have secure, unique passwords
Given the proliferation of online services and their associated user accounts, it’s practically impossible to avoid an attack in which your personal information may be stolen. Consider some recent exploits:
- Sony Playstation Network (2011)
- Steam (2011)
- Epsilon (2011)
- Gawker (2010)
- Network Solutions (2009)
Not only have these services and many others been breached due to vulnerabilities in deployed software and/or operations, but they’ve also shown that most services do not adequately secure user credentials and information. In perhaps the most egregious example, Gawker silently truncated passwords at 8 characters and then stored them as an unsalted hash, for which rainbow tables were conveniently available. In this case, even if a user is diligent, and has created a sufficiently long and secure password, he or she is still vulnerable due to a poor technical implementation by the service provider.
One can rightly make the case that the ball is in the user’s court, and the only secure password is a unique one used once per site, managed through a centralized password database like KeePass or LastPass. And I think that’s a good case to make, but I don’t want to let service providers and software engineers off the hook just yet – I think we can do a much better job and I’d like to address three points in particular:
- A strong and secure technical implementation for the storage of user credentials.
- A password policy or ruleset that promotes the creation and usage of secure passwords.
- And this is important: Always permit users to securely delete their accounts.
Secure Technical Implementation
This one’s on the engineers, and while we’ve seen plenty of poor implementations outed after the fact, it hasn’t been for a lack of guidance: RFC 2898: PKCS #5 <http://tools.ietf.org/html/rfc2898> was published in 2000 and remains good policy today. In particular, Password-Based Key Derivation Function #2, henceforth PBKDF2, specifies that the password be stored as a uniquely salted one-way hash (using SHA1-HMAC, for instance). Usage of a unique salt or nonce eliminates the potential for an entire database to be exposed via pre-computed rainbow tables while another feature, the iteration count or work-factor, applies the hash function repeatedly in a bid to slow brute-force attacks.
Selecting an appropriate work-factor is a balance between the security of users’ credentials and the performance of an authentication service. While RFC2898 suggests 1000 iterations for PBKDF2, keep in mind that it was published in 2000, when the fastest processors had only a single core and clocked in around 1 GHz. Today, a safe iteration count for PBKDF2 is probably in the tens of thousands.
Of course, the real metric is not iteration count, but latency. The iteration count should be tuned to the maximum permissible authentication latency given the performance requirements of the service (authentications per second) and user tolerance. 10ms isn’t long for a user to wait, nor expensive to a service in the context of a once-per-session cost, but it is quite expensive indeed for an attacker looking to brute-force a password database (100 hash operations/core/sec as opposed to potentially billions of MD5 hash operations/core/sec on commodity hardware).
Alternatives: bcrypt and scrypt
While an implementation of PBKDF2 with a strong hashing algorithm and sufficient work factor (say 20,000 iterations in 2012) is a good solution, it is already over a decade old at this point and new developments have emerged to challenge it.
The advent of GPGPU has resulted in an order of magnitude increase in computational performance for parallel workloads, like brute-force password cracking. Vijay Devakumar’s blog post on the subject is illustrative of the tools available to modern-day password crackers. In fact, cloud-based GPGPU computing makes it even easier for attackers to put together an entire farm of GPUs, as pointed out in Thomas Roth’s blog. GPUs are particularly effective for established and otherwise secure hashing algorithms like SHA-512, which leads us to find alternatives to PBKDF2, namely: bcrypt and scrypt.
bcrypt <http://static.usenix.org/…> has been around slightly longer than PKBDF2, though it is a more memory intensive algorithm, and should theoretically provide much better protection against GPGPU accelerated attacks by virtue of the fact that it cannot fit within the on-die cache. There is a substantially newer option, however, which should provide much better protection from brute-force attacks, right now and into the future: Colin Percival’s scrypt <http://www.tarsnap.com/scrypt.html>. scrypt takes the idea of a scalable work factor (such as the iteration count in PBKDF2) and extends it further to memory cost as well as computational cost.
From Stronger Key Derivation via Sequential Memory-Hard Functions (2009):
Definition 1. A memory-hard algorithm on a Random Access Machine is an algorithm which uses S(n) space and T (n) operations, where S(n) ∈ Ω T (n)1−ǫ.
A memory-hard algorithm is thus an algorithm which asymptotically uses almost as many memory locations as it uses operations5; it can also be thought of as an algorithm which comes close to using the most memory possible for a given number of operations, since by treating memory addresses as keys to a hash table it is trivial to limit a Random Access Machine to an address space proportional to its running time.
Storing User Credentials Securely
Ideally, given one of the secure key derivation functions discussed above, a secure user account record should look something like this:
- Password Hash
- Salt (nonce)
- Iteration Count or Work Factor (if applicable)
If PKBDF2 is in use, it’s a good idea to store the iteration count in the password record. This allows the schema to support a greater number of iterations in the future, to keep pace with advancing hardware. Likewise, the Version field can be used to deprecate obsolete records and algorithms as needed.
A Sensible and Secure Password Ruleset
Now that the implementation details have been thoroughly covered, let’s discuss password rulesets. Rulesets exist to enforce a minimum degree of entropy for a user’s password. They typically enforce a minimum length constraint and some kind of minimum character set (usually alphanumeric with some symbols). What’s typically more frustrating, however, is not what these rulesets require, but rather what they prohibit: a large variety of printable ASCII characters (often times including periods `.’ and even spaces). Some sites enforce a maximum length or silently truncate, as was the case with Gawker in 2010. It was even recently revealed that Blizzard’s Battle.net – the centralized account management system for World of Warcraft, Diablo, and Starcraft – ignores case in user passwords, presumably by forcing the password to a single case before applying a secure hashing algorithm.
The only sensible password ruleset is a byte steam with a minimum entropy requirement. Byzantine rules demanding one numeral in the middle of a password and at least one capital letter are easily defeated by lazy users who will simply respond with “Passw0rd1”.
Managing the Lifetime of Your User’s Online Identity
Many data-miners and CRM experts are likely to balk at my final point, but it is absolutely essential that users be permitted to securely delete their accounts, thereby managing the lifetime of their online identity.
Think about every account you’ve ever created. Every Facebook app you’ve used, every discussion forum you’ve posted in, every online game you’ve played, and on and on ad infinitum. The average user has left a rather sizable digital footprint on the Internet, and most simply don’t realize the extent of it.
Suppose you’re a savvy user who has secure, unique credentials everywhere, managed via a password database. Perfectly secure, right? But what about 10 years ago? What long-forgotten accounts from the past are still lurking out there, “secured” in a database with unsalted MD5 hashes just waiting to be exploited? What if you can’t delete them because you simply aren’t given the option?
Working Towards a Secure 2012 and Beyond
Engineers and decision makers have all the tools necessary to protect their users’ credentials and, if the past few years have been any guide, plenty of reason to do so.
We have standards for secure key derivation functions like PBKDF2, but ideally what we need is a standard that defines account security end-to-end: from the technical implementation, to the password ruleset and lastly, account lifetime management. I’d like to see services commit to such a standard publicly, like SSL, so users can be confident that their online identities will be managed securely.
In the meantime, savvy users will have to rely on the factors under their control:
- Use unique passwords with high entropy and management tools like KeePass and LastPass
- Use two-factor authentication where available (RSA hard tokens and mobile authenticators)
- Think carefully before storing your personal and financial details with a new service
References and Further Reading
- RFC2898: PKCS #5: Password Based Cryptography Specification Version 2.0 <http://tools.ietf.org/html/rfc2898>
- Stronger Key Derivation via Sequential Memory-Hard Functions <http://www.tarsnap.com/scrypt/scrypt.pdf>
- bcrypt <http://bcrypt.sourceforge.net/>
- scrypt <http://tarsnap.com/scrypt/>
- StackExchange: Thomas Pomin on bcrypt <http://security.stackexchange.com/a/6415>
- StackExchange: Thomas Pomin on PBKDF2 <http://security.stackexchange.com/a/3993>