This is in response to a Tenable blog post "Do Passwords Matter?" I have several issues with the post that I address here.
When discussing password cracking, the post says "A 'salt' will help slow down this process a little." Actually, salts slow down the process a lot. It's still no more difficult to brute-force an individual user, but it becomes insanely hard to brute force all of the accounts for a large set of hashes (e.g. the 6million+ hashes dumped from LinkedIn). With salts, it's six million times harder to crack six million passwords than to crack one. Salts also prevent rainbow tables and other precomputation attacks completely. The Tenable post points out that developers sometimes implement salts incorrectly. That's really beside the point. Just because some developers get it wrong doesn't mean the others should stop trying to get it right.
Side note: rainbow tables are not as powerful as people think they are. Looking up a large number of users in rainbow tables is prohibitive. They are useful for attacking one or a small number of users, but that's it. At one minute per lookup, it would take over a decade to use an existing rainbow table against all of the LinkedIn hashes.
The post goes on to say that "even if salts are implemented correctly, the processing power of GPUs can be
used to crack the salted password hashes in more time, using even larger
pre-computed password dictionaries than ones without a salt." This is utter nonsense. With 128-bit salts (as used in bcrypt) it's impossible to create rainbow tables for all or even a significant portion of the possible salt values.
Imagine that you want to create rainbow tables for all 8 character,
lower-case, alphanumeric passwords. There are about 2**41 possible
combinations. Assuming no wasted computation (and making rainbow tables
wastes plenty), you’d need to perform around 2**169 computations to make
rainbow tables for all 2**128 salts. If you wanted to perform a brute force attack against the 6.5m LinkedIn
passwords using the same character set, you’d only need to perform about
2**64 computations. So the effort to create the rainbow tables would
be 2**105 times greater than brute-force. If you had a supercomputer
that could brute force 2**64 in 1 second (and for bcrypt that’s insane),
the universe would die a heat death long before you finished.
Rainbow tables require anywhere from hundreds of megabytes to multiple
gigabytes of storage. Currently, we can store about a terabyte on a
hard drive (2**40 bytes). If you needed to store a 1 gigabyte rainbow
table (or set of tables) for each salt, you’d need about 2**158 bytes of
storage. That means you’d need 2**118 terabyte hard drives or 2**108
one petabyte hard drives.
On the topic of password complexity, the posting points out that many users will use the weakest password allowable given the site policy. It points out that attackers can guess billions of passwords a second using GPU hardware. This is true and it's one of the reasons for salting and stretching passwords. Salting forces an attacker to consider each user individually; his cracking efforts no longer scale. For instance, if salting is used and two users both have the password "P@ssw0rd", an attacker will not be able to know that the passwords are the same and will have to guess passwords for each user separately which doubles the work effort to crack both.
With stretching, the passwords are hashed using using an algorithm that is deliberately slow (possibly by iterating a fast algorithm thousands of times as in PBKDF2). Stretching can be used to slow down cracking so that an attacker can only guess 100 passwords per second or less on a fast CPU. This prohibits the use of rainbow tables since an attacker can no longer brute force all possible combinations for even a moderate length password. Instead, the attacker will have to use dictionary-based attacks. He can still crack badly chosen passwords, but it is time consuming and would be extremely prohibitive to crack a significant number of passwords for a large site.
An attacker can improve his efforts somewhat using GPU hardware, but he still will not be able to launch a brute-force attack for any reasonable length of password. To further cramp the attacker's efforts, developers can use a password hashing scheme such as scrypt which is designed to be "memory-hard." This prevents the use of GPU based password crackers because they only have a limited amount of memory per processor core.
An attacker can still crack a small number of weak passwords, but with bcrypt/scrypt in place he may only be able to recover a few hundred badly-chosen passwords instead of millions.
SSL and Password Sniffing
In some cases, an attacker may be able to impersonate a site or launch a man-in-the-middle attack to allow him to harvest passwords. But, this is generally much harder than just using SQL injection and provides less benefit to the attacker. SQL injection is a drive-by attack that requires little persistence. Launching an ongoing series of man-in-the-middle attacks against a large website would require an attacker to have an established presence on network of the site or its ISP. So the attacker has to be an insider or find another way to break in before beginning this attack. I don't want to downplay this too much because it's important to use SSL and to get it right, but the fact that some risk still exists here doesn't excuse choosing bad passwords or storing them improperly.
NTLM sucks. No argument.
Password length doesn't matter a lot if the passwords have a clear pattern (e.g. "asdfghjkl;12345" or "LinkedInP@ssw0rd"). I played around with the LinkedIn hashes and cracked a lot of passwords that were 14-15 characters. Passwords need to be longer and more random, not just longer.