As the LinkedIn password leak continues to occupy the time and attention of password-crackers, I thought it might be worth mentioning another high-profile site which apparently uses unsalted hashes.
Two weeks ago, I discovered that Apple sends an unsalted SHA-256 hash as part of an AppleID authentication process. I was looking at traffic from my iPad using MITM Proxy, and came across the following interesting packet:
[Note — I changed the AppleID and password hash fields, and also blocked out the exact host and URL].
The “pwdHash” caught my eye, both because, well, it’s a hash, and also because it looked like a 256-bit hash, which I’d been finding used in some other commercial iOS apps lately. But mostly, it caught my eye because there wasn’t any field labeled “salt.” This might not mean anything — the salt might be known to both parties, and so doesn’t need transmitting. Or maybe it’s a shorter hash, and the first 16 bytes are a salt. Still…it’s worth checking out.
Which I did. Turns out, passing my password through a SHA-256 hash created a duplicate hash value:
You might also notice a complete lack of any other session-related information in the HTTP header or in the submitted XML. There’s nothing else for the server to go on, other than this hash and the accompanying AppleID.
So, from this I’m inferring one of two things: Either Apple’s got a database of unsalted SHA-256 password hashes for AppleIDs (bad), or they’ve got a database of plaintext passwords for AppleIDs (worse). Either way, I was really surprised by this.
So what’s the best way to store password hashes, anyway? There’s been a lot of talk about exactly this over the past day or so, and while almost everyone agrees that unsalted hashes are bad, it’s harder to find agreement on what kind of salt is appropriate.
Probably the best argument (in terms of immediate security and foreseeable longevity) is made in favor of algorithms that make use of [key stretching](http://en.wikipedia.org/wiki/Key_stretching features to increase hash strength. Bcrypt, Scrypt, and PBKDF2 have been frequently cited as good candidates. These algorithms use a high work factor, that’s difficult to avoid with faster hardware or parallelization, to ensure that brute-force attempts are very very slow. You can read more about how bcrypt, for example, makes these sorts of attacks much more difficult in this short blog post from 2010. Yes, two years ago. It’s not like these problems, or their solutions, are new.
Are you responsible for the development, maintenance, or security of an application that uses password hashes as part of an authentication system? Open your calendar now, and set aside some time in the next week to look at how you do things and see if it couldn’t be made better. Hopefully, your users will never have need to thank you.
Update: Jeff Jarmoc (@jjarmoc) correctly points out that the hashes don’t have to be stored exactly as transmitted — they could simply be used as input for a more secure hash, like one described above. Even Apple is storing the unsalted hashes, they could easily update the servers to a system which stores (for example) the bcrypt of the hash. The nice thing about this is it should only require changes to the server, not to individual clients.