Ashley Madison - Sloppy Crypto Reveals Passwords Even With Top Quality Cryptography Hashing
How did crackers break the passwords of Ashley Madison, even though they used the Bcrypt hashing method, which should be difficult to crack the hashed passwords? With Bcrypt the hashing process is slowed down with a number of rounds of hashing, which makes it difficult to crack as it takes too long to produce the hashed values [Bcrypt background].
In the end over 11.2 passwords were cracked from the Ashley Madison database. In fact 2.6 million passwords were cracked in just a few hours, using a single CPU (and not reverting to multi-core GPUs).
Introduction
After many articles explaining what you were not safe by hashing passwords using standard password hashing methods (such as SHA-1), and that Bcrypt should be used, someone goes can cracks millions of password hashes from the Ashley Madison [here] and where Bcrypt has been used.
Apart from the normal weaknesses of the human spirit, software developers also often extremely poor when it comes to implementing proper cryptography methods. From things that should be uncrackable, using bullet proof methods, we end up with implementations which are equivalent to using a password of "password". Of all the reviews I've done of cryptography implementations, there also a place where the whole thing falls apart.
The method is good ... the implementation is terrible!
So how did the crackers break Bcrypt? Well the developers made a good choice in Bcrypt, with a cost factor of 12, but it was the implementation of two insecure methods of creating the $loginkey variable (which is used for automatic login, and then modified on a change of account details) that they were able to crack For this they went to the Git dump of the code, and analysed the code to create the hashed value.
It involved weaknesses in the code involving:
md5(lc($username).”::”.lc($pass))
and
md5(lc($username).”::”.lc($pass).”:”.lc($email).”:73@^bhhs&#@&^@8@*$”)
Salted MD5 cracking
The crackers first analysed the amlib_member_create() function in amlib_member_create.function.php, and which used a method of:
$loginkey = md5(lc($username).”::”.lc($pass))
where lc() is lowercase. So we have an MD5 hash of the username ("bill") added to the password ("PassWord"):
$loginkey = md5("bill::password")
This would have been relatively easy to crack, but the develop generated the password from Bcrypt:
$pass = encryptPassword($pass)
$loginkey = md5(lc($username).”::”.lc($pass))
where the encryptPassword() method used Bcrypt. This addition of Bcrypt was an addition added on June 2012, so that all the passwords created before June 2012 could be easily cracked from salted MD5 hashed values. The lowercase conversion also significantly reduces the power of the hash, making it easier to crack.
To give you an idea, a 7 digit lowercase password has 26^7 possible passwords (8,031,810,176) as apposed to 52^7 possible passwords (1,028,071,702,528), which is 128 times more difficult to crack. With crackers running at 10GHashes per second (10 billion per second) it doesn't take too long to crack a simple hash such as MD5. Try this to examine password strengths:
https://asecuritysite.com/encryption/passes
Password reset goes back to MD5
Next they looked at the generateLoginKey() function, which is called when the user changes their details, in AccountProvider.php and found:
$loginkey = md5(lc($username).”::”.lc($pass).”:”. lc($email).”:73@^bhhs&#@&^@8@*$”).
which is a different way to generate $loginkey, and now uses the username, password and email address, with a constant salt string called $hash (73@^bhhs&#@&^@8@*$), and then hashed with MD5. On an account change the $loginkey variable will then be changed with the updated method.
In this case ....
Bcrypt was not used!!!!!
which meant that the crackers could break the hash values which had been changed by users, or recovered their accounts (which could happen quite often for a site such as this).
Conclusion
What a sloppy mess! In the end over 11 million passwords were cracked, even though there was some attempt to protect the hashed passwords with Bcrypt. Unfortunately, it was piecemeal crypto with no real focus and a lack of a coherent strategy and testing.
The site implemented Bcrypt, which should have been difficult to crack, but then did not implement it with a password reset, or where there was a change of details. This is negligent in the extreme for a site like this. The cracking of the MD5 hash is so simple these days, and is just a matter of trying a range of salts to produce a match.
One thing that is important in software development for high-risk sites is to perform an audit on the code where each line of code is reviewed, often with a complete walk-through. This would normally identify the password change problem and also the differing methods of hashing. Developers on high-risk sites really have to have strong procedures for change control, and in code reviews.
The terseness of PHP, too, really does not help in producing robust code, as the code involved is often hacked together, rather than using proper software development methods. The usage of the lc() method to convert the password to lowercase is extremely poor practice, and passwords which can take three months to crack can be cracked in less than a day.
The final part of the sloppy procedure is the use of a secret salt value (73@^bhhs&#@&^@8@*$) which is fine if it is kept secret, but once everyone knows what the salt it, there is virtually no security applied to the hashing method.
Once must wonder why companies continue to implement their own security methods and implement horrible code, with taking the advice of external parties. A single code review would have spotted most of these problems.
You must wonder why so few universities teach secure coding, and cryptography, as part of their Computer Science courses, but it really can't continue, especially in stopping breaches such as this one. The methods used for software development too, in this case, go back to a time when code was hacked together. Again, in a high risk area such as this one, there are no excuses for not doing a code review, and application testing. Developers often need to have a thick skin, and expose their code for reviews, especially in high risk areas.