Page 1 of 2
Passwords are pure MD5-Hashes?!
Posted: Thu Feb 01, 2007 12:46 pm
by brar
Hi there,
I just found out that that s9y is using 'unsalted' MD5-Hashes to store the passwords into the database.
I found out because another user is using the same password as me which results in the same hash.
It is a common techniqe to "salt" the passwords by concatenating them with the user name before hashing them.
This has two advantages:
- 1. The hash of the same password looks different for two users so nobody can see that another user is using the same password.
2. It is a simple protection to rainbow table attacks.
I don't know about any disadvantage (for backward compatibility one can try the unsalted hash if the salted hash fails).
Usually this feature can be implemented with one to several (few) lines of code - if I had any Idea of PHP i'd supply a patch
Any Plans?
Regards,
Brar
Re: Passwords are pure MD5-Hashes?!
Posted: Thu Feb 01, 2007 12:49 pm
by garvinhicking
Hi!
You are right, s9y does not use that salt. If we were to use it, it would require updating all stored hashes.
But it's a good suggestion, and updating the stored hashes should not be that hard.
However, there might be plugins that access the user authentication themselves (like hte "User Self-registration") plugin, and they would need to be changed as well. So if people upgrade to the new core s9y version, their plugin would no longer work. And people that wrote custom plugins might also need to upgrade it.
But maybe that is worth the trouble, so I'm gonna chew and think on this a little more and try to find out which of our plugins would be affected...
Best regards,
Garvin
Re: Passwords are pure MD5-Hashes?!
Posted: Thu Feb 01, 2007 12:50 pm
by garvinhicking
Ha. Wait.
We can't update the MD5 hashes, because we don't know the passwords of the users.
We could update the hash on first login, but that would mean we need to accept logins for people that still have the old MD5 hash. And having that BC code to allow such logins would then still allow people to steal their hashes like before...
Best regards,
Garvin
Posted: Thu Feb 01, 2007 1:39 pm
by brar
Ok, Plugins make things a bit more complicated but I still think it is worth thinking about it.
I don't know about s9y internals but how about using (and recommending for plugins) a method like
authenticate(user, password, passwordstyle){
...
}
where passwordstyle is a configurable option with values like 'old', 'new' and 'migrate'
which handles the internals of fallback to old style hashes and (if wished - expressed by 'migrate') successively migrates them to new style hashes?
Regards,
Brar
Posted: Thu Feb 01, 2007 1:51 pm
by garvinhicking
Hi!
Yes, but we would need to use the fallback method also for the new logins in the core, because old user accounts cannot be migrated to new ones automatically. You would need to enter the password of every existing user. Even an admin can't do that because he usually does not know the passwords of all his users...
Best regards,
Garvin
Posted: Thu Feb 01, 2007 2:55 pm
by brar
Yes, but we would need to use the fallback method also for the new logins in the core
Yes, but I think it doesn't hurt.
Ok I try to express mself in code - please excuse if it doesn't run out of the box but I'm C# guy who transfers old perl knowledge to PHP here.
Code: Select all
authenticate($user, $password){
$passwordstyle = get_configured_password_style();
$hashfromdb = get_hash_fromdb($user);
if($passwordstyle == 'new'){
$newhash = new_hash_method($user, $password);
if($hashfromdb == $newhash){
return true;
} else{
return false;
}
} else if($passwordstyle == 'old'){
$oldhash = old_hash_method($password);
if($hashfromdb == $oldhash ){
return true;
} else{
return false;
}
} else{ #$passwordstyle == 'migrate'
$newhash = new_hash_method($user, $password);
if($hashfromdb == $newhash){
return true;
} else{
$oldhash = old_hash_method($password);
if($hashfromdb == $oldhash ){
update_db_with_new_hash($user, $newhash);
return true;
} else{
return false;
}
}
}
}
The methods
Code: Select all
get_configured_password_style()
get_hash_fromdb($user)
new_hash_method($user, $password)
old_hash_method($password)
update_db_with_new_hash($user, $newhash)
should be self explaining
Best regards,
Brar
Posted: Thu Feb 01, 2007 3:15 pm
by garvinhicking
Hi!
Using this would implicate that the authenticate() method always first needs to check if the MD5 hash is unsalted and allow a login if it is.
This would then mean every use could force himself to login if he has a unsalted MD5 somewhere from pervious "hack" attempts.
And, one more question: If I know the username of a person, and I am able to crack the MD5 checksum of an unsalted password - can't I then also crack the MD5 checksum because I know the salt?
Regards,
Garvin
Posted: Thu Feb 01, 2007 4:04 pm
by brar
Using this would implicate that the authenticate() method always first needs to check if the MD5 hash is unsalted and allow a login if it is.
Yes, the 'migrate' passwordstyle would only be as secure as the 'old' style (in fact even less as there are two valid hash values instead of one). Only configuring to 'new' style (for new installations or after migration of all accounts) would give you increased security.
And, one more question: If I know the username of a person, and I am able to crack the MD5 checksum of an unsalted password - can't I then also crack the MD5 checksum because I know the salt?
Yes!
But a rainbow table attack works by having tables of prehashed passwords (common passwords for small tables).
There is less chance that I've got prehashed values for a salted password as I can't foresee the username + password combination.
So salting passwords isn't an overall solution for protecting weak passwords against attacks but it makes rainbow table attacks a little harder.
Have a look at this impressive site!
http://www.plain-text.info/
If you worry about hash collisions you could use sha-1 or better sha-256/sha-512 (see
http://www.heise.de/security/news/meldung/77235 (german)) or perhaps Whirlpool or RIPEMD as hash algorythm.
I don't know about PHP support for advanced hash algorythms.
Regards,
Brar
Posted: Sun Nov 18, 2007 3:51 pm
by freggy
I'm reviving this old thread. There currently is some discussion about this problem on LWN.net:
http://lwn.net/Articles/258857/
This really needs further attention, as there are some important disadvantages to not using salting.
Posted: Mon Nov 19, 2007 10:10 am
by garvinhicking
Hi!
Maybe there's someone experienced with hashing/salting/md5/encryption mechanism who wants to lend a hand in adding support for that to s9y?
I am not that well experienced in the area, so I don't want to worsen the situation by patching it only half the way.
Regards,
Garvin
Posted: Mon Nov 19, 2007 8:08 pm
by chickens
Why not just sha1 the md5? It is a little bit of work, but will provide the most backwards compatibility. Simply below is what I am thinking:
Code: Select all
$password = "test";
$md5_pass = md5($password);
$stored_password = sha1($md5_pass);
Then you can take anywhere the md5_pass is stored and sha1 it to make it compatible with the latest version. To upgrade the update script would just convert the md5 passwords into sha1 passwords. This would provide the most security with the least amount of breakage.
From a security standpoint md5 is like a toy car and sha1 is like a tank. Both can be compromised, but the tank is going to stand on its own two legs for that much longer. Even with a salt md5 can be broken fairly easily, I've done it a few times in my security research.
Posted: Tue Nov 20, 2007 11:15 am
by garvinhicking
Hi!
But isn't a sha1()'ed password without salt as insecure as a md5 hash? And couldn't stealing the sha1() hash then provide the same rainbow table attack vector?
Would you maybe like to dive deeper into code to see how to implement this hashing mechanism?
Regards,
Garvin
Posted: Wed Nov 21, 2007 1:48 am
by chickens
I will take a look at the code later to see what I can figure out. I am on vacation from work this week, so I should have the time to take a deep look at the code.
I am first going to do a bit of research to find out what the best possible PHP hashing method will be. SHA1 is good, but I know that there are much better algorithms out there. I am just not sure what is currently available in PHP natively.
Posted: Wed Nov 21, 2007 7:52 am
by chickens
It looks like this might be a good time to join the
gophp5 project.
With php4 you are extremely limited to what you want do encryption wise. With php5 you can use
hash() to encrypt the passwords in nearly anything you want. If we do a sha256 or sha512 using the hash function it would be great. sha256 and sha512 can not currently be brute forced with rainbow tables or anything else at this point in time.
With php4 you are pretty much limited to a maximum of
sha1() without recreating a function to do the encryption. If we do this then there is always a chance for an error and it will be slow.
Seeing that php4 is going to be unsupported after the first of the year I would recommend switching to php5 just for the encryption options.
I will continue to look at both options until I get some further input on the subject.
Posted: Wed Nov 21, 2007 11:38 am
by garvinhicking
Hi!
I dislike the gophp5 project, I think I've commented here on the forum about it. I see no reasons to add a php5 deadline for projects that run perfectly fine on php4 as well. This artifical limit is IMHO only bad for the end-users.
IMHO we could simply use sha when PHP5 is available, and stay with a md5-hash + salt with PHP4? What are the performance implications of using such a strong hashing mechanism?
I do not see this sha-encryption as a reason to force PHP5 onto the user...there must be a way to do it differently.
Regards,
Garvin