linuxbashshellhashcat

Using hashcat where first 10 character of hash are known


I've web application that use MySQL

The application use password hash function from MySQL to store the password for related account

The problem is, it trim the hashed password so that it only store first 10 characters into the password field

I want to prove to my supervisor that, trimming hashed password can make different password to be entered on the login form and accepted by the application. Because those passwords has same first 10 character

To prove that, I'm planning to use hashcat. I've download quite big dictionary file to help my purpose

So, is there someone can help me how is the parameter that I should use in hashcat?

I've tried to google for the answer, but no luck

Thanks


Solution

  • 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 passwordhashed passwordfirst 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:

    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.