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 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.