SHA512 without salt
#1
I've got a group of hashes that appear to be SHA512 (start with $6, have the number of rounds listed in the $rounds=5000 format) but don't have a salt. -m 1800 doesn't work and I've tried to tweak the hashes a few different ways but so far no luck so I figured I'd check with the community.

Redacted Example:  $6$rounds=50$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Thanks,

Matt
#2
Ok I did some digging into this one and was able to figure out what you've got.

My initial assumption was that the salt was null and that what you had was equivalent to "$6$rounds=5000$$", which assumes the hashes were generated with an extremely forgiving parser. My first thought was PHP's implementation of crypt(3). So I whipped up a quick test script to see how PHP reacts if you specify the iteration count without a salt:

Code:
epixoip ~ $ cat test_crypt.php
<?php

$hash = crypt('1234', '$6$rounds=5000');
$prefix = substr($hash, 0, strrpos($hash, "$"));

if (crypt('1234', $prefix) === $hash)
    print "authenticated\n";
Code:
epixoip ~ $ php test_crypt.php
$6$rounds=5000$gTCqLuWlyVt5bMqH3Rkivs4IbqY7IHbXgy1wf5dguojI3ugG6YJUcFKBydYxZafs7uBmA/JftaYYgFLn8ls5U.
authenticated

Ok, so if we generate a hash specifying only the iteration count, PHP returns a hash string with only the iteration count, which matches the format you described above. However, if we plug that hash into Hashcat, it cannot parse it. We need to determine how to reformat the hash values so Hashcat will accept them.

Again my initial assumption was that the salt was null. But Hashcat was unable to crack it after reformatting it as "$6$rounds=5000$$", so the salt must not be null.

I dug a bit deeper to see what PHP is really doing:

Code:
epixoip ~ $ cat test_crypt2.php
<?php

$hash[0] = crypt('1234', '$6$rounds=5000');
$hash[1] = crypt('1234', '$6$rounds=5000$rounds=5000$');
$hash[2] = crypt('1234', '$6$rounds=5000$rounds=5$');
$hash[3] = crypt('1234', '$6$rounds=5000$$');
$hash[4] = crypt('1234', '$6$$rounds=5000$');

print_r ($hash);
Code:
epixoip ~ $ php test_crypt2.php
Array
(
    [0] => $6$rounds=5000$gTCqLuWlyVt5bMqH3Rkivs4IbqY7IHbXgy1wf5dguojI3ugG6YJUcFKBydYxZafs7uBmA/JftaYYgFLn8ls5U.
    [1] => $6$rounds=5000$rounds=5000$gTCqLuWlyVt5bMqH3Rkivs4IbqY7IHbXgy1wf5dguojI3ugG6YJUcFKBydYxZafs7uBmA/JftaYYgFLn8ls5U.
    [2] => $6$rounds=5000$rounds=5$IG27pqK3wRZZmvxQmsbgwypnxrEYxqW03z1uURbb1gZDe6RexmrYwPkPjqurIrt6Rl2DnzyEa3ZF8XfenPCRp0
    [3] => $6$rounds=5000$$9gHD3IKAdgRfbqpvcQKBuR7Z2sV.9sRSsxWTw/s7NlyE4BSbUBEi0RfvVb0FK1jmtgIrMLkO.T5WM4xIZGcqU1
    [4] => $6$$9gHD3IKAdgRfbqpvcQKBuR7Z2sV.9sRSsxWTw/s7NlyE4BSbUBEi0RfvVb0FK1jmtgIrMLkO.T5WM4xIZGcqU1
)

Ok that's interesting. Again I would have expected '$6$rounds=5000' to be the same as '$6$rounds=5000$$', but it's not. From this output, it is obvious that "rounds=5000" is being used as the literal salt value, and not the iteration count! This makes sense though, internally PHP is checking to see if the salt contains three fields, or only two fields. If it only sees two fields, then it uses the second as the salt value. This is perfectly reasonable and is logical. Except in the case when rounds is null and you specify a salt, PHP seems to just ignore both. That's not quite logical.

Hashcat really doesn't like the above hashes, it mangles up a lot of them and has a lot of trouble parsing them, indicating there are likely some bugs in our -m 1800 parser. However, one of them works perfectly:

Code:
epixoip hashcat-3.40 $ ./hashcat64.exe --quiet -a 3 -D 1 -m 1800 '$6$rounds=5000$rounds=5000$gTCqLuWlyVt5bMqH3Rkivs4IbqY7IHbXgy1wf5dguojI3ugG6YJUcFKBydYxZafs7uBmA/JftaYYgFLn8ls5U.' 1234

$6$rounds=5000$gTCqLuWlyVt5bMqH3Rkivs4IbqY7IHbXgy1wf5dguojI3ugG6YJUcFKBydYxZafs7uBmA/JftaYYgFLn8ls5U.:1234

SUCCESS!

So all you need to do to crack these hashes is change the format of the hashes from "$6$rounds=5000$" to "$6$rounds=5000$rounds=5000$" and Hashcat will happily crack them for you. And since you only have one salt for all hashes, you'll be able to crack at full singe salt speed, which is tremendously helpful since sha512crypt is pretty slow.
#3
Wow, this is a very nice analysis @epixoip! Well done!

That's some very precious knowledge about how PHP deals with a zero-length salt for sha512crypt (or better said, no salt at all) ... and might be crucial information for other users in the future (that have the same type of hashes - without salt -)

I'm not sure about the "a lot of trouble parsing" and "some bugs in our -m 1800 parser" though, do you think this is worth a github issue?
#4
Yeah, I'm going to open an issue for a few cases I ran into. Some quick examples:

When I input `$6$$rounds=5$gTCqLuWl...` hashcat turns it into `$6$$rounds65qgTCqLuWl...`

When I input `$6$rounds=5000$rounds=5$gTCqLuWl...` hashcat turns it into `$6$rounds=5$gTCqLuWl...`, which it then subsequently cannot parse in the potfile for the very reason this thread exists.
#5
Thanks a ton for all the work on this! Great job.

(06-29-2017, 11:00 PM)epixoip Wrote: Ok I did some digging into this one and was able to figure out what you've got.

My initial assumption was that the salt was null and that what you had was equivalent to "$6$rounds=5000$$", which assumes the hashes were generated with an extremely forgiving parser. My first thought was PHP's implementation of crypt(3). So I whipped up a quick test script to see how PHP reacts if you specify the iteration count without a salt:

Code:
epixoip ~ $ cat test_crypt.php
<?php

$hash = crypt('1234', '$6$rounds=5000');
$prefix = substr($hash, 0, strrpos($hash, "$"));

if (crypt('1234', $prefix) === $hash)
   print "authenticated\n";
Code:
epixoip ~ $ php test_crypt.php
$6$rounds=5000$gTCqLuWlyVt5bMqH3Rkivs4IbqY7IHbXgy1wf5dguojI3ugG6YJUcFKBydYxZafs7uBmA/JftaYYgFLn8ls5U.
authenticated

Ok, so if we generate a hash specifying only the iteration count, PHP returns a hash string with only the iteration count, which matches the format you described above. However, if we plug that hash into Hashcat, it cannot parse it. We need to determine how to reformat the hash values so Hashcat will accept them.

Again my initial assumption was that the salt was null. But Hashcat was unable to crack it after reformatting it as "$6$rounds=5000$$", so the salt must not be null.

I dug a bit deeper to see what PHP is really doing:

Code:
epixoip ~ $ cat test_crypt2.php
<?php

$hash[0] = crypt('1234', '$6$rounds=5000');
$hash[1] = crypt('1234', '$6$rounds=5000$rounds=5000$');
$hash[2] = crypt('1234', '$6$rounds=5000$rounds=5$');
$hash[3] = crypt('1234', '$6$rounds=5000$$');
$hash[4] = crypt('1234', '$6$$rounds=5000$');

print_r ($hash);
Code:
epixoip ~ $ php test_crypt2.php
Array
(
   [0] => $6$rounds=5000$gTCqLuWlyVt5bMqH3Rkivs4IbqY7IHbXgy1wf5dguojI3ugG6YJUcFKBydYxZafs7uBmA/JftaYYgFLn8ls5U.
   [1] => $6$rounds=5000$rounds=5000$gTCqLuWlyVt5bMqH3Rkivs4IbqY7IHbXgy1wf5dguojI3ugG6YJUcFKBydYxZafs7uBmA/JftaYYgFLn8ls5U.
   [2] => $6$rounds=5000$rounds=5$IG27pqK3wRZZmvxQmsbgwypnxrEYxqW03z1uURbb1gZDe6RexmrYwPkPjqurIrt6Rl2DnzyEa3ZF8XfenPCRp0
   [3] => $6$rounds=5000$$9gHD3IKAdgRfbqpvcQKBuR7Z2sV.9sRSsxWTw/s7NlyE4BSbUBEi0RfvVb0FK1jmtgIrMLkO.T5WM4xIZGcqU1
   [4] => $6$$9gHD3IKAdgRfbqpvcQKBuR7Z2sV.9sRSsxWTw/s7NlyE4BSbUBEi0RfvVb0FK1jmtgIrMLkO.T5WM4xIZGcqU1
)

Ok that's interesting. Again I would have expected '$6$rounds=5000' to be the same as '$6$rounds=5000$$', but it's not. From this output, it is obvious that "rounds=5000" is being used as the literal salt value, and not the iteration count! This makes sense though, internally PHP is checking to see if the salt contains three fields, or only two fields. If it only sees two fields, then it uses the second as the salt value. This is perfectly reasonable and is logical. Except in the case when rounds is null and you specify a salt, PHP seems to just ignore both. That's not quite logical.

Hashcat really doesn't like the above hashes, it mangles up a lot of them and has a lot of trouble parsing them, indicating there are likely some bugs in our -m 1800 parser. However, one of them works perfectly:

Code:
epixoip hashcat-3.40 $ ./hashcat64.exe --quiet -a 3 -D 1 -m 1800 '$6$rounds=5000$rounds=5000$gTCqLuWlyVt5bMqH3Rkivs4IbqY7IHbXgy1wf5dguojI3ugG6YJUcFKBydYxZafs7uBmA/JftaYYgFLn8ls5U.' 1234

$6$rounds=5000$gTCqLuWlyVt5bMqH3Rkivs4IbqY7IHbXgy1wf5dguojI3ugG6YJUcFKBydYxZafs7uBmA/JftaYYgFLn8ls5U.:1234

SUCCESS!

So all you need to do to crack these hashes is change the format of the hashes from "$6$rounds=5000$" to "$6$rounds=5000$rounds=5000$" and Hashcat will happily crack them for you. And since you only have one salt for all hashes, you'll be able to crack at full singe salt speed, which is tremendously helpful since sha512crypt is pretty slow.