So, I took time out from decorating to trawl the Internet, as is my wont. I came across a nice site with Apache Mod_Rewrite cheat sheets which is nerdy, but useful. The same site also has a nice article about Writing Secure PHP which is pretty good – although I have some comments…
So I’m a nerd for security, and I do like overkill, but there are some simple things that could be done to improve the security described in the ‘Weak Passwords’ section on page 2.
First off, don’t use MD5. It’s broken , or at least it would be better (and very little effort) to use SHA-1.
Second, if you’re storing the hash (MD5, SHA-1, SHA-256, whatever) of a user’s password, well, don’t just hash the password, but hash the username too. PHP’s Crypt() function is for this kind of thing, with a ‘salt’. E.g.
Function EncryptPassword( $username, $password ) {
$salt = substr($username,0,2);
return crypt($password, $salt);
}
What would this mean? Well, an attacker trying the dictionary attack described would need not 1, but 3844 dictionaries, assuming usernames are alphanumeric and case sensitive.
Hell, why not use the username too as what you’re hashing? I’ve not seen this done anywhere – and I’m not sure of it’s security (I say that in the most paranoid sense) – but principle is the same. By appending the username to the password being hashed, well, you’d need a seperate dictionary for each username. You could even throw in a constant string – it doesn’t add much security, but it means your code would have to be compromised in order to allow precomputation of a dictionary for a user.
Function MakeHash( $username, $password ){
return sha1( $username . "some arbitrary string" . $password);
}
A final thought – don’t underestimate passphrases rather than passwords. They’re easier for people to remember than passwords. Consider ‘r5GG8%’ and ‘elephants lollop gracefully’. Which would you remember? Robert Hessig of Microsoft PSS has a good article. And all of the above techniques would work with a passphrase instead of password – after all, they’re all just text…
Comments from my old blog:
DES was broken many years ago, so that’s a very poor alternative to MD5.
Puzzled by the DES comment – DES isn’t a good algorithm for encryption, certainly – it’s bust, and we have AES now. Also, DES is a block encryption cipher, whereas MD5 is a hashing algorithm. Different things.
I believe the DES comment is because your EncryptPassword function passes crypt a two character salt, which makes crypt use the ‘standard DES-based encryption’.
Ah, well I’ll be damned. I hadn’t realised that Crypt could use DES. Come to that, I’m not sure why I’m using a Crypt function for what should be hashing. Brain fade, I guess. I suppose that replacing DES with Blowfish would give a function that encrypted the password in a recoverable way, although I’m not a fan of that.