For an answer to the actual question skip to the last section of this answer. The other sections do not answer your question directly, but you may find that this is not neccessary anymore after reading them.
Your Description Of The System
You said the system processes the password as follows
plaintext password
➜ hashed password
➜ first 10 characters of the hash
Example:
Topsecret123
➜ *E7C95D33E14D3C2A3AE4EAB25C1D98C88593F7AC
➜ *E7C95D33E
Note that MySQL's PASSWORD()
prefixes hashes with a *
, so you actually only include 9 characters from the hash.
Answering The Question In The Background
You asked how to find hash collisions for the approach from above using hashcat, but what you actually wanted to know/show was
prove trimming hashed password can make different password [...] accepted by the application.
Your emphasis was on »Trimming causes multiple passwords to be accepted«. However, you overlooked that even untrimmed hashing causes multiple passwords to be accepted.
The Pigeonhole Principle
The explanation is so simple that you don't have to find a hash collision. Everyone should understand the following:
- There is an infinite amount of passwords.
- MySQL password hashes have a fixed length, precisely 64 bit. There can be only 264 different hashes.
- The password hash function maps passwords to hashes. Since there are more passwords than hashes some passwords have to be mapped to the same hash.
If not, you would have found a compression function which would allow you to store anything in only 64 bits.
One may argue that the number of valid passwords is not infinite. But even if you would limit valid passwords to be of exactly length 11 and contain only symbols from the group [A-Za-z0-9]
(has 62 symbols) there would be 6211 unique passwords:
6211 ≈ 5,2×1019 passwords
264 ≈ 1,8×1019 hashes
Therefore, there still have to be lots of collisions.
Hash Collisions
Trimming hashes is not the root cause of the collision problem, but of course it increases the likelihood of collisions enormously. Normally, hash collisions are not a problem because they happen so rarely that you don't encounter them. However, with strongly trimmed hashes like yours, collisions become a real problem.
Finding A Collision
Using Hashcat
hashcat can compute MySQL password hashes with -m 300
. You can confirm this by computing SELECT Password("hashcat");
and comparing the resulting hash with the hash shown here.
However, I couldn't find a way to trim these hashes / look for prefix collisions. I guess hashcat cannot do what you want. You would have to implement a custom hashmode for hashcat. The easiest way to do this would be to alter the current implementation of hashcat's MySQL mode. I'm not sure, but maybe it is sufficient to just change const int out_len = 40;
to 9
. You may have to update the OpenCL versions of the same module too. Search for m00300
here.
Using A Custom Script
Alternatively, look for a list of password-hash-pairs or generate one yourself, then look for prefix collisions in that table. This was fun so I did it myself
The following python program generates trimmed hashes for some numerical passwords:
#! /usr/bin/python3
import hashlib as hl
def mySqlPwHash(password):
return hl.sha1(hl.sha1(password.encode()).digest()).hexdigest()[:9]
for number in range(0, 300000):
password = str(number)
print(password, "\t", mySqlPwHash(password))
I chose to generate 300'000 hashes because there are 169 trimmed hashes and we can expect to find a collision in √(169) = 262'144 tries (see birthday problem).
To find passwords with the same hash run the script as follows:
./collide.py | sort -k2 | uniq -Df1
In only two seconds the script finished and printed
23607 47ae310ff
251848 47ae310ff
And there you have it, two passwords (23607
and 251848
) with the same trimmed hash (47ae310ff
).
If your trimmed hashes actually include 10 hex-digits you can adapt the script and will find the two passwords 1874547
and 2873667
sharing the hash 47fc464b2f
.