PHP crypt() returning wrong answer
Asked Answered
P

5

9

I think i'm losing my marbles here... I've got a problem on my web site where randomly it stops accepting logins. I've now been able to trace it to crypt() behaving very strangely.

In my database, i've got the crypted version of the users password - so let's say Og12345678.

When the user logs in, they enter their password, I read the salt out of the db and then crypt what they entered and compare - usually this works very well.

So i'm doing crypt($enteredPassword, $saltFromDb) - in this case, the salt would be Og of course. Normally for a given users password crypt works fine.

When things go wrong (and when they do it's a permanent change until I restart Apache) I found that crypt starts returning a DIFFERENT answer for the same input with the same salt.

It's consistent however, i.e. once the system has gone wrong crypt returns the wrong answer but it's always returning the same wrong answer. Repeated refreshes of the page show the same output. The same salt is also in evidence in the newly incorrect crypt result also, so it's not that the salt has gone missing somewhere.

If I then restart Apache and re-run the script without any changes at all, the results from crypt are then back to how they should be.

I appreciate it's not the latest PHP (5.2.8) but would value any views on this including whether it's a known bug fixed in a later version (upgrading PHP is not a happy task with lots of sites some of which still use unfortunate quirks that all need to be re-tested with each upgrade) - if it is a known fixed bug then obviously i'll get it all upgraded ASAP, beyond that it'll probably be easier to outsource the crypt externally since I only use it in one common place for my site.

Any input appreciated.

Matt Peddlesden

--- Update: 11 Mar 2011

Correction to comment previously given about operating system... - Operating system is Windows Server 2008 SP1 64 bit. Apologies I should have double checked rather than assuming I could remember! Machine is a Dell 2950 8gb Ram, Xeon processors.

I am starting to think along the lines Krtek is suggesting - when the system has gone wonky, if I generate new crypt() (i.e a very simple example where i set a variable to a string, crypt it and then compare with the crypt) - all works great. When I restart the server, again it's all back to the previous calculations again. So I am definitely leaning towards something that is changing the algorithm used to calculate the crypt() result... any thoughts on what might cause this to happen? I printed out the values of the CRYPT_STD_DES etc and they don't change between restarts.

Anyone got any clues on what might cause this to happen?

Whatever it was seemed to happen twice in one day yesterday, most odd.

Thanks for the answers thus far.

--- Update: 16 Mar 2011

Just wanted to provide another update.

This is still happening, still no further understanding of why.

In case anyone comes across this in the future, I think my solution going forwards is going to be to do some nasty hack to push all the crypt() executions out to an external C# application and stop having to rely on PHP to do them. Something is going wrong somewhere and at this point the only solution I can see is to remove it from the equation entirely.

Of course if it still happens, that will be interesting to know too! :)

Thanks all.

Poultryman answered 10/3, 2011 at 11:11 Comment(3)
I think it's unlikely that this is your problem, but I see that the advice in the PHP documentation -- php.net/manual/en/function.crypt.php -- is that you should pass the whole (salted) crypted password in as the salt. if (crypt($enteredPassword,$cryptedPasswordFromDB) == $cryptedPasswordFromDB) { ... }. The point seems to be that then crypt() can determine what hashing algorithm is in use from $cryptedPasswordFromDB. Again, I doubt that this is the cause of your problem, but you might give it a go...Delorsedelos
Is it possible than a script change some php configuration resulting in a different hash function used by crypt ? Like said by @Gareth passing the complete password from the db can solve this problem.Labor
I am starting to think along the lines Krtek is suggesting - when the system has gone wonky, if I generate new crypt() (i.e a very simple example where i set a variable to a string, crypt it and then compare with the crypt) - all works great. When I restart the server, again it's all back to working again. So I am definitely leaning towards something that is changing the algorithm used to calculate the crypt() result... any thoughts on what might cause this to happen? I printed out the values of the CRYPT_STD_DES etc and they don't change between restarts.Poultryman
D
2

Why are you reading the salt? And how are you getting the salt? Different algorithms use different methods for including the salt in the output.

Just use the whole output of the crypt function as the second argument:

  $crypted='Og12345678';
  if (crypt($_POST['password'], $crypted)==$crypted) {
      ....

And single pass DES? Really?

Last time I looked, the PHP crypt implementation would call the crypt() function provided by the system - so if it has broekn then its more likely to be your OS than PHP - but you didn't say what your OS is.

Detestation answered 10/3, 2011 at 12:42 Comment(5)
OS is Windows Server 2008 SP2. Thanks for your comments.Poultryman
Only letting me add single line comment :) - I have adjusted the code to use the full password in the crypt() command and this didn't help when the system went wrong again a moment ago.Poultryman
Yes, Single pass DES, the system was written a long time ago and to be honest it doesn't protect anything even remotely secure, it just lets people download files from the site. The whole site is up for a re-develop in to a new technology at some point. But yes, point taken :)Poultryman
erk, if it really is the crypt() fn that's the problem (and not elsewhere in the PHP/database code) then you might try a blowfish encrypted password - IIRC, MSWindows does not provide a blowfish implementation - so if you get the same behaviour there, it points to problems in PHPs implementation of crypt() rather than the OS.Detestation
Presumably this would mean re-encrypting all the passwords in the database however, not something I can do without forcing all the users to re-enter new passwords, as I don't store the plaintext version. I'll keep it in my back pocket though... thanks!Poultryman
O
1

It might be the Suhosin PHP security patch affecting your crypt() function. It alters a lot of the encryption/random methods and may be the the cause of your problem.

Check a phpinfo() and see if 'suhosin' is anywhere on the page. If it's there, look into disabling some of it's features in the php config.

Oyer answered 10/3, 2011 at 11:26 Comment(1)
Thanks for your comments, i've checked the phpinfo() and it does not have any suhosin bits mentioned anywhere on it, so I presume this doesn't apply.Poultryman
H
1

i had the same problem with crypt... I had that login-check working on 2 servers, but when i transfer it to the newest one it eventually stop working. I walk around it with md5 encryption as follows: In register.php

 $encrypted = md5($_POST["pass"]);
 ...

And then in login.php

$password = md5($_POST["password"]);
 if ($password == $row["hash"])
        {
            // remember that user's now logged in by storing user's details in session
            $_SESSION["id"] = $row["id"];
            $_SESSION['username'] = $_POST['username'];
            $_SESSION['logged'] = 'Yes';
            // redirect to homepage
            redirect("index.php");
        }

I hope that helps :)

Herrmann answered 16/8, 2013 at 17:11 Comment(0)
G
0

I faced the same problem. Since moving my vTigerCRM installation to local machine, user login with previously stored passwords started failing. It seems like crypt() is returning different hashes on different environments with the same arguments:

On local environment:

SYSTEM: Windows NT 6.1 build 7601 (Business Edition Service Pack 1) i586
PHP: 5.3.5

crypt('hello world','$1$ad0000000'):

     $1$ad00000008tTFeywywdEQrAl9QzV.M1

On production environment:

SYSTEM: Linux 2.6.18-338.9.1.el5.lve0.8.32 #1 x86_64
PHP: 5.3.5

crypt('hello world','$1$ad0000000'):

    $1$ad000000$8tTFeywywdEQrAl9QzV.M1
Gillette answered 21/8, 2011 at 7:31 Comment(1)
I bet it's not a crypt() issue, it's jut Windows :P What happens if you use the same parameters in other non-windows OS like RedHat, Solaris, Debian?Brennabrennan
K
0

Maybe this helps someone..

For me the problem was that i forgot to include this code:

if (!defined('PASSWORD_BCRYPT')) {
/**
 * PHPUnit Process isolation caches constants, but not function declarations.
 * So we need to check if the constants are defined separately from 
 * the functions to enable supporting process isolation in userland
 * code.
 */
define('PASSWORD_BCRYPT', 1);
define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);
define('PASSWORD_BCRYPT_DEFAULT_COST', 10);
}
Kirsti answered 6/4, 2023 at 20:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.