2

Long story short, I've got some passwords that were improperly salted and hashed in a version of PHP that allowed the crypt() function to fall back to the CRYPT_STD_DES algorithm if the salt was invalid.

However in PHP 5.3.2+:

5.3.2 Fixed Blowfish behaviour on invalid rounds to return "failure" string ("*0" or "*1"), instead of falling back to DES.

What makes this a problem is that the salt contained the "$" character as it was intended to be a blowfish salt (but was unknowingly malformed).

Thus I am unable to manually do something like the following: crypt($pass, "$a"); since that is not a valid CRYPT_STD_DES salt either now. The salt must be in the range "./0-9A-Za-z". It simply returns "*0" as the PHP devs intended.

How can I validate these malformed passwords in a more recent version of PHP (at least 7.1, ideally)?

That Guy
  • 29
  • 7
  • If a DES hash was created, what salt does it contain, does it really contain the $ character? Could you show the first part of such a DES hash string? – martinstoeckli May 13 '20 at 14:30
  • @martinstoeckli The salt is "$2" in this case. The beginning of a hash (for example) would be "$281kuD" plus 6 more chars. – That Guy May 14 '20 at 23:05

3 Answers3

0

you are probably looking for

password_hash ( string $password , int $algo [, array $options ] ) : string

https://www.php.net/manual/en/function.password-hash.php

Anylyn Hax
  • 301
  • 2
  • 10
  • That function is only for hashing the passwords. I need to validate them first before I can upgrade to a modern hash algorithm. – That Guy May 13 '20 at 02:56
0

As a workaround, I ended up actually using the old version of PHP for a single directory where I could make a file_get_contents() call and retrieve a hash with the old (bugged) algorithm, but still use the more modern version of PHP elsewhere.

This is not a proper solution, however, as it technically does not answer the question: "How can I validate these malformed passwords in a more recent version of PHP?"

As such, unless there appears to be no other possible solution, I will not be marking this as the accepted answer (but I believe this answer should be added for completeness sake).

That Guy
  • 29
  • 7
0

Found an actual solution. By bruteforcing the salts, it turns out that PHP was interpreting the invalid "$2" STD_DES salt as "q2".

Therefore, the answer to this question is that one can validate these hashes in a newer version of PHP by altering the salt used to compare the hashes so that it begins with "q2" instead of "$2". From there, it's possible to just call substr_replace($str, '$', 0, 1); to replace the newly added "q" character back to a "$" character when performing the equality check.

As an anecdote, apparently the information I had was incorrect and the hashes were generated in PHP 5.3.29 which contradicts what the docs say about falling back to STD_DES being patched in version 5.3.2.

That Guy
  • 29
  • 7