Password Cracking Tutorial
Introduction — UNIX Passwords
UNIX passwords are stored using what is called a
hashing algorithm. When a user first enters his password, it is run through a one-way algorithm that converts it to a new string. Then, when he subsequently tries to log in, the system hashes what he types and checks it against the stored hashed password.
The hashing algorithm used should be
one-way, meaning the actual password cannot be obtained from the hashed one. Additionally, it should avoid
collisions, where two different strings hash to the same result.
The algorithm used for this was DES, which is actually an older encryption algorithm dating to 1979. This was found to be relatively weak, and more modern systems moved to a true hashing algorithm, MD5. However, though it is still very widely used for system passwords, it has been found to have flaws and should not be used for any kind of custom authentication system. Stronger alternatives, such as SHA2, are now common in secure systems.
Cracking UNIX Passwords
So how do we recover passwords if the algorithm cannot be reversed? The answer is to use
brute force, where every possible password is hashed and compared to the hashed password. If they match, the password has been found.
A smarter approach is to use a
dictionary attack, where words from the English language or other languages are tried first. Many users will have simple words as their passwords, and this attack is much faster - an 8 character random password can have 44^8 possibilities (with symbols and numbers), where there are only about 30,000 commonly used English words.
Additionally, many cracking programs, such as
John the Ripper, which we'll be using, try permutations of english words in order to increase success rate, such as adding numbers to the end of a word or reversing the letters.
Depending on the quality of the password, this can be quite fast, on the order of seconds or minutes. A well-made password, with random characters, numbers, and symbols, can take much longer, but is still feasible given enough processing power.
Storing UNIX Passwords — Salt and Shadowing
Initially, the idea was that the algorithm for passwords cannot be reversed, so there was no need to hide the hashed passwords. Thus, the
/etc/passwd file had all of the usernames and passwords of everyone in the system. Clearly, this is not actually secure.
passwd file has lines in the following format:
<username>:<hashed password>:<userid>:<groupid>:<information>:<home directory>:<default shell>
Passwords in UNIX do have
salt, which is a 12 to 32-bit string appended to the password and hashed with it. This salt is stored in clear text with the password hash. When a user sets a password, this salt is generated, appended to the password, and the result is hashed. The salt, in clear text, is also stored in the
passwd file so that it can be applied to what the user later enters to login.
Then what is the point, if our cracking program can simply read and use the salt? The purpose is to ensure two users who set the same password do not then have the same hash, as well as to slow down password cracking.
Salting does not slow down the cracking of a given password significantly, but it does make it much less efficient to crack many passwords by requiring that each one take the salt into account while being tested.
A more effective solution to prevent cracking that has since become common is to
shadow the password file. Shadowing is essentially allowing the
passwd file to remain world-readable, but moving the passwords to
/etc/shadow, in the same format as before, and making
/etc/shadow readable only by root.
Thus, only those with root privileges can read the encrypted passwords in the first place. This requires that programs to log users in or change the password must have root privileges to do their job, but prevents a given user from reading other user's passwords.
Analysis of a Packet Capture (use password.pcap)
The passwords you will be cracking for this lab are provided in a pcap file. The file was created using the tcpdump utility and contains all network traffic that passed through netsec-demos at the time of listening. During the test, 10 http requests were made from from netsec-demos to hamsa that contained authentication data for 10 different users. They were sniffed with the following command:
sudo tcpdump -i eth1 -s 0 -w password.pcap
Once you have retrieved the tcp packet dump from the link above, you will need to examine its contents using
Wireshark. Being that
Wireshark runs with a GUI, we will need to setup X11 forwarding, which will allow us to forward the windows from an SSH connection to our local machine. To do this, logout of any SSH session you have running, and reconnect to hamsa with the -X flag. Since the GUI over SSH produces a lot of traffic, consider doing this part with a partner or else on your local machine:
$ ssh -X USER@hamsa.cs.northwestern.edu
After logging in, run
Wireshark. Open the capture file from wherever it was saved in the previous step and you will see something similiar to what is shown below:
$ wireshark packetdumpname.pcap
Wireshark's filter textbox can be used to limit the packets shown to those of interest. Since we know that we are only concerned with HTTP traffic, this might be a good place to start.
Wireshark is a powerful tool on which an entire tutorial could be written, but the Wireshark Wiki is a great place to start. To give you some hints for this portion of the exploit, the user will browse some websites before attempting to login to the server in question. Your goal is to filter through the packets and find the ones where user credentials are sent. Another hint, his credentials are sent in the clear, but not in plain text. Try looking for something that is base64 encoded.
Once you've found the passwords, you can simply copy and paste the data line by line into a file to feed into
John the Ripper. Don't worry about any of the formatting- John will recognize it as is.
Trying Out Password Cracking
John the Ripper is a fast, multi-platform password cracker. We will be cracking 10 passwords. Run the following setup. Note: this package will only run on hamsa, don't try to use it on your own machine.
$ john John the Ripper password cracker, ver: 1.7.9-jumbo-7 [linux-x86-xop] Copyright (c) 1996-2012 by Solar Designer and others Homepage: http://www.openwall.com/john/ Usage: john [OPTIONS] [PASSWORD-FILES] <SNIPPED>
You will also need a dictionary. The package above comes with one (password.lst) that will be sufficient for this lab.
To start, save your hashes from above in the format "username:$1:$salt:$passwordhash" (simply copying them from wireshark should be sufficient). $1 indicates MD5 as the hash type. MD5 is one of the more common hashing schemes for UNIX passwords, though it is also particularly insecure. We will assume your file is called
Now we have john, a dictionary of lowercase words, and a list of hashed passwords to crack. John works by applying certain transformation rules to a set of original words. For example, default rules on the supplied word "password" will try "password123", "PASSWORD", "p4ssw0rd" and thousands of other combinations. In order to select wordlists and transformation rules, you'll need to learn some usage and syntax.
$ ./john --show ./passwd.crack
John remembers the passwords it cracks from run to run. Show them with this command.
$ ./john --single ./passwd.crack
This will do a "single crack". It is the most basic cracking scheme john has. It will crack something like "admin:admin".
$ ./john --wordlist=password.lst ./passwd.crack
This will use your wordlist with some additional default rules.
$ ./john --wordlist=password.lst --rules=Extra ./passwd.crack
This explictly states the rules you want to use, "Extra". To find out what these rules actually are you'll want to check out the file
./john.conf. In normal scenarios you'll want to start with the "Single" rules (which is not the same as --single), then "Extra", and then possibly "Jumbo" or custom rules. The determining factors for what rules to try will always be the type of the hash and size of the wordlist as these determine how quickly your cracking will run. The
Single rules will be sufficient for this lab.
$ cat john.conf | grep -A 10 -m 1 Extra [List.Rules:Extra] # Insert/overstrike some characters... !?A >[1-6] l i\0[a-z] !?A l o0[a-z] !?A >[1-7] l o\0[a-z] # Toggle case everywhere (up to length 8), assuming that certain case # combinations were already tried. -c T1 Q M T0 Q -c T2 Q M T[z0] T[z1] Q -c T3 Q M T[z0] T[z1] T[z2] Q -c T4 Q M T[z0] T[z1] T[z2] T[z3] Q
Some of these rules are pretty complicated and you aren't expected to understand them. More important is to understand what the existing rules will not catch and write rules to catch them. We will focus on the following rule:
!?A >[1-6] l i\0[a-z] * !?A : do not run on words with capital letters * >[1-6] : for each 1 to 6, if the word is greater than that length do the following (note, John will not accept two digit numbers for either of the bounds) * l : convert to lowercase (?) * i : insert at the following index the following character * \0 : references result of range [1-6] * [a-z] : for each range [a-z]
Effectively this will insert all letters a-z from position 1-6 in the word, hash it, and compare it against the hashes you're cracking.
To get a better understanding you may want to check the docs.
Use john to crack
at least 8 of the 10 passwords.
Note the default John the Ripper rules will not crack the following passwords:
* passw0ord # inserted number at index 6 * passworrd # inserted letter at index 7 (or 8) * easypass # two words
You will need to write rules to catch passwords of this form.
Hint #1: easypass isn't in your wordlist because it is a combination of two words. Once you've cracked all of your simple passwords, write a script to transform your wordlist such that it now contains all permutations such as easypass and passeasy. John won't do this for you (because in the common case 2n length words are too long). Then run john with the new wordlist and the default rules.
Write your rules as
[List.Rules:NewRule] at the very end of
john.conf. This should get you started:
[List.Rules:NewRule] !?A >[1-9] l i\0[a-z]
You can then use your rules with the following command.
$ ./john --wordlist=password.lst --rules=NewRule ./passwd.crack
For the classwork, you had two adjustments to make: combinations of words and insertions. What about passwords that combine both of these strategies?
* easy+pass # two words, + inserted at index 4
This exercise requires running the previous rules on the new wordlist. You'll notice this takes a lot longer than the previous steps. This is how a good password can be hard to crack.
Hint #2: Passwords are from length 4-10 and can only contain alphanumerics or the symbols !@#$%^&*-=_+.?|:'".