Understanding and Cracking Password Hashes 12-05-2018, 10:44 PM
#1
Introduction
Password hashes can be very challenging to crack. I see a lot of people online who just don't understand how password hashes work or even how they are made. I will use the PHP interactive shell in some cases during the tutorial. I will try to add as many links throughout the tutorial for extra research and reading.
Hash Identification
One of the most important parts for cracking a hash is identifying what type of hash you have. The JTR website (openwall) has a nice list of hashes that can help you identify what type of hash you have, https://openwall.info/wiki/john/sample-hashes. It is important to be able to recognize hashes. I am a fan of regular expressions so let's do some regex and see if we can make something that identifies (or attempts to identify) hashes.
We'll start with an easy one, MD5, which will also match the first 32 characters of SHA-1
SHA-1 is always 160 bits, 40 characters
BCrypt
One-Way Hashing
MD5 is a widely used one-way hashing function. One-way hashes are difficult to crack. When you hash a string, with MD5 for example, you take two inputs and get one output. In 2008 the CCC showed us that they could use collision checking to forge new SSL certificates. Since then, Verisign does not generate SSL certificates with MD5. This is a flaw in the MD5 one-way hashing algorithm. There is another kind of "collision" checking that is pretty basic and is used by most "md5 cracking" websites. That is to generate a hash of a known word and check it against the hash the user is trying to crack. The problem with this brute force method is the same as other brute force methods, it's fucking time consuming.
Salts
When you create an MD5 password hash you probably want to do it with a salt. A salt is like a special code/passphrase to add that extra layer of protection to the hash. If you hash a password with a salt, chances are, that unless a person has the hash and the salt, it won't be cracked. I'm not saying it can't be cracked. The PHP password_hash function automatically generates a random salt if you don't provide one.
There are different ways to use salts but one way is to just append the salt to the password or the hash and hash it again. Below is some PHP code that uses a salt to change the MD5 of the password. Typically you would store the salts out of your web directory or in a different database to prevent hackers from cracking password hashes. Also, in the example I use the word 'haha' as the salt, you should use a random string of characters.
Generating Hashes
Let's see what kind of hashes PHP can make for us and what they look like.
MD5
SHA1
PHP password_hash with bcrypt
PHP password_hash by default
In Python, to generate and print an MD5 hash you can use hashlib.
Simple Collision Cracking
I have been in arguments with people who think that because a hash appears to be an MD5 hash, makes it an MD5 hash. This isn't the case for all hashes. Let's say we have a password, password. We can hash that thing as much as we want with other algorithms and then hash it with MD5. People who don't understand how it was originally hashed will just think it's some strong password that can't be cracked. It's password for christ sake, it can be cracked. You can crack it open if you know HOW it was created in the first place. Some people want you to crack a hash but can't even tell you what software it came from. For example, let's hash up the password hash a few different ways.
Above we have wrapped the md5 in a SHA1. To crack the password we cant simply check it with a sha1() php function, using a hash collision as stated before. We would need to use sha1(md5()), since that was how it was created. Below is a sample function to show how you would construct something like that.
And running it in the terminal would give you..
You can do some research on your own and dive into some open software forums and see how they hash their passwords. Most use BCrypt now and not just regular MD5, a topic here for MyBB shows the hashing algorithm for MyBB 1.x. So the code above you could simply change it to accommodate for the salt and different way they hashed their password, and you have created yourself a MyBB 1.x password cracker. It's neat to learn.
Cracking Hashes with JTR
The best password cracker I have ever used is JohnTheRipper. I have been using this software for over 10 years, maybe 15? I forget. The point is, it works. You can find all kinds of guides for using it on many different websites and forums. Basically you will create a file with your password hashes in it, then feed it to John. You don't have to supply a username if you don't want, and you don't even have to supply a wordlist if you don't want. At the time of writing this JTR is in version 1.8. You can see some commands below for download, unzipping and installing john, from source.
Download
Unzip
Install
When you install john it will go through a benchmark and depending on the speed of your processor(s), it can be fast or slow. If you want the jumbo version of JTR you can get it from Github. I recommend this version. Below is how to clone it into a new repo.
Once you clone it, move into the src directory and build it with the following commands, as stated in the documentation.
After you have cloned it and built it you can start cracking hashes immediately, however I suggest giving it a benchmark. If you are cracking a list of MD5's, this is probably the version you want. You can get started by using the following command (changing the filenames of course).
and you can view the cracked passwords for that file like this..
Password hashes can be very challenging to crack. I see a lot of people online who just don't understand how password hashes work or even how they are made. I will use the PHP interactive shell in some cases during the tutorial. I will try to add as many links throughout the tutorial for extra research and reading.
Hash Identification
One of the most important parts for cracking a hash is identifying what type of hash you have. The JTR website (openwall) has a nice list of hashes that can help you identify what type of hash you have, https://openwall.info/wiki/john/sample-hashes. It is important to be able to recognize hashes. I am a fan of regular expressions so let's do some regex and see if we can make something that identifies (or attempts to identify) hashes.
We'll start with an easy one, MD5, which will also match the first 32 characters of SHA-1
Code:
([0-9a-zA-Z]{32})\b
SHA-1 is always 160 bits, 40 characters
Code:
([0-9a-zA-Z]{40})\b
BCrypt
Code:
\$2y\$.{56}
One-Way Hashing
MD5 is a widely used one-way hashing function. One-way hashes are difficult to crack. When you hash a string, with MD5 for example, you take two inputs and get one output. In 2008 the CCC showed us that they could use collision checking to forge new SSL certificates. Since then, Verisign does not generate SSL certificates with MD5. This is a flaw in the MD5 one-way hashing algorithm. There is another kind of "collision" checking that is pretty basic and is used by most "md5 cracking" websites. That is to generate a hash of a known word and check it against the hash the user is trying to crack. The problem with this brute force method is the same as other brute force methods, it's fucking time consuming.
Salts
When you create an MD5 password hash you probably want to do it with a salt. A salt is like a special code/passphrase to add that extra layer of protection to the hash. If you hash a password with a salt, chances are, that unless a person has the hash and the salt, it won't be cracked. I'm not saying it can't be cracked. The PHP password_hash function automatically generates a random salt if you don't provide one.
There are different ways to use salts but one way is to just append the salt to the password or the hash and hash it again. Below is some PHP code that uses a salt to change the MD5 of the password. Typically you would store the salts out of your web directory or in a different database to prevent hackers from cracking password hashes. Also, in the example I use the word 'haha' as the salt, you should use a random string of characters.
Code:
php > $salt='haha';
php > echo md5($salt.'password');
2ea2cc5eb47e586063f472eb0a4b718e
php > echo md5('password');
5f4dcc3b5aa765d61d8327deb882cf99
Generating Hashes
Let's see what kind of hashes PHP can make for us and what they look like.
MD5
Code:
php > echo md5('hello world');
5eb63bbbe01eeed093cb22bb8f5acdc3
SHA1
Code:
php > echo sha1('hello world');
2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
PHP password_hash with bcrypt
Code:
php > echo password_hash('hello world', PASSWORD_BCRYPT);
$2y$10$9s0RLal7aReKjMfo4.l1y.1SaOXkWWEEAMOonA9kAOX4wTgOI8dRG
PHP password_hash by default
Code:
php > echo password_hash('hello world', PASSWORD_DEFAULT);
$2y$10$FojyTgEdUx6sU7e1eYU4a.hf1QfhbRaXafITOR80hbHYi.84UF2Ay
In Python, to generate and print an MD5 hash you can use hashlib.
Code:
(xenial)sunjester@localhost:~$ python
Python 2.7.12 (default, Nov 12 2018, 14:36:49)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import hashlib
>>> hash = hashlib.md5(str.encode('password'))
>>> print hash.hexdigest()
5f4dcc3b5aa765d61d8327deb882cf99
Simple Collision Cracking
I have been in arguments with people who think that because a hash appears to be an MD5 hash, makes it an MD5 hash. This isn't the case for all hashes. Let's say we have a password, password. We can hash that thing as much as we want with other algorithms and then hash it with MD5. People who don't understand how it was originally hashed will just think it's some strong password that can't be cracked. It's password for christ sake, it can be cracked. You can crack it open if you know HOW it was created in the first place. Some people want you to crack a hash but can't even tell you what software it came from. For example, let's hash up the password hash a few different ways.
Code:
php > echo sha1(md5('password'));
55c3b5386c486feb662a0785f340938f518d547f
Above we have wrapped the md5 in a SHA1. To crack the password we cant simply check it with a sha1() php function, using a hash collision as stated before. We would need to use sha1(md5()), since that was how it was created. Below is a sample function to show how you would construct something like that.
Code:
<?php
//return true/1 if the word we give it is the password
function crackPass($hash, $word)
{
return sha1(md5($word)) == $hash ? true:false;
}
echo crackPass("55c3b5386c486feb662a0785f340938f518d547f", "password")."\n";
?>
And running it in the terminal would give you..
Code:
(xenial)sunjester@localhost:/var/www/html$ php crack.php
1
You can do some research on your own and dive into some open software forums and see how they hash their passwords. Most use BCrypt now and not just regular MD5, a topic here for MyBB shows the hashing algorithm for MyBB 1.x. So the code above you could simply change it to accommodate for the salt and different way they hashed their password, and you have created yourself a MyBB 1.x password cracker. It's neat to learn.
Cracking Hashes with JTR
The best password cracker I have ever used is JohnTheRipper. I have been using this software for over 10 years, maybe 15? I forget. The point is, it works. You can find all kinds of guides for using it on many different websites and forums. Basically you will create a file with your password hashes in it, then feed it to John. You don't have to supply a username if you don't want, and you don't even have to supply a wordlist if you don't want. At the time of writing this JTR is in version 1.8. You can see some commands below for download, unzipping and installing john, from source.
Download
Code:
wget https://www.openwall.com/john/j/john-1.8.0.tar.xz
Unzip
Code:
tar -xvf john-1.8.0.tar.xz
Install
Code:
sudo make GENERIC
When you install john it will go through a benchmark and depending on the speed of your processor(s), it can be fast or slow. If you want the jumbo version of JTR you can get it from Github. I recommend this version. Below is how to clone it into a new repo.
Code:
git clone https://github.com/magnumripper/JohnTheRipper.git
Once you clone it, move into the src directory and build it with the following commands, as stated in the documentation.
Code:
sudo ./configure && make -s clean && make -sj4
After you have cloned it and built it you can start cracking hashes immediately, however I suggest giving it a benchmark. If you are cracking a list of MD5's, this is probably the version you want. You can get started by using the following command (changing the filenames of course).
Code:
(xenial)sunjester@localhost:~/Downloads/JohnTheRipper/run$ ./john -wordlist=password.lst -format=raw-md5 /home/sunjester/Downloads/passwords.txt
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-MD5 [MD5 128/128 SSE4.1 4x3])
Warning: no OpenMP support for this hash type, consider --fork=2
Press 'q' or Ctrl-C to abort, almost any other key for status
password (admin)
1g 0:00:00:00 DONE (2018-12-05 13:54) 25.00g/s 4800p/s 4800c/s 4800C/s 123456..knight
Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably
Session completed
and you can view the cracked passwords for that file like this..
Code:
./john -format=raw-md5 -show /home/sunjester/Downloads/passwords.txt