Computer Science Department - University of Puerto Rico
Prepared by: José R. Ortiz-Ubarri
A password file contains the password of the users of a system.
Examples are the OS shadow file, database password file, apache password file
man crypt
The crypt() function performs password encryption, based on the NBS Data Encryption Standard (DES).
For Good:
For Bad:
John the Ripper password cracker
John the Ripper is a fast password cracker, currently available for many flavors of Unix, Windows, DOS, BeOS, and OpenVMS. Its primary purpose is to detect weak Unix passwords. Besides several crypt(3) password hash types most commonly found on various Unix systems, supported out of the box are Windows LM hashes, plus lots of other hashes and ciphers in the community-enhanced version.
http://www.openwall.com/john/
The eassiest passwords to crack are dictionary passwords.
Yes it is.
Check your/usr/share/dict/words
file in your Unix or garden of Unix machines.
Otherwise google for it.
The one we will use has 479,623 words.
Simply test the crypted password of each user against a crypted version of each word in the dictionary.
In python use the crypt function.
import crypt
crypt.crypt(cleartextpasswd, salt or cryptedpasswd)
will return the clear text password crypted.
root:$1$TKuJpECV$h2VaRm0dzYHe4W3TuErqj/:14882:0:99999:7::: jortiz:$1$gzN9bqPH$NYUvr/GzmQOQYDTXWtpUG/:14915:0:99999:7::: mysql:!!:15724:::::: bill:$1$EUDeA5rZ$eUZf1JdTwYkbKW6XIhgag1:15876:0:99999:7::: juan:$1$pNZcxGAV$UXzkOMRDdNEA5TfLIjGce0:15876:0:99999:7::: ramon:$1$C93hlZvi$Ekc.7ADTlFm3xqeRmUAvF/:15876:0:99999:7::: felipe:$1$jUWA/Uz0$pvAecsNoesrw.lv9eM7Sn0:15876:0:99999:7::: maria:$1$M.6iuNRQ$qQpbYXe/vQE/xJPaG2SjK0:15876:0:99999:7::: victor:!!:15876:0:99999:7:::
Splitting each line of this file would return a list with: username in position 0 and the crypted password in position 1.
Very light version.... Very....
shadow_lines = readShadow(sys.argv[1])
word_lines = readWords(sys.argv[2])
for i in range(len(word_lines)):
word = word_lines[i].strip()
for user in shadow_lines:
user = user.split(":")
if crypt.crypt(word, user[1]) == user[1]:
print "User %s, password %s" % (user[0], word)
Note user[0] is the username and user[1] contains the crypted password.
It will depend on the number of users in the password file and the number of words in the dictionary file.
Our algorithm will take O(|shadow_lines| x |word_lines|)
The example we will use would take around half an hour to finish.
Not that long, if the results are worth...
So we have 479,623 words.
A small cluster with 12 cores.
A password file with passwords <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< words
So lets divide the dictionary among the cluster cores and have each core check the portion of the dictionary assigned against each password.
if rank == 0:
shadow_lines = readShadow(sys.argv[1])
else:
shadow_lines = None
shadow_lines = comm.bcast(shadow_lines, root=0)
n1, n2 = computeIndices(len(word_lines), num_procs, rank)
# Shrink words from memory. Trust in the GC
word_lines = word_lines[n1:n2]
for word in word_lines:
word = word.strip()
for user in shadow_lines:
user = user.split(":")
if crypt.crypt(word, user[1]) == user[1]:
print "User %s, password %s" % (user[0], word)
Note that I am taking advantage of having a shared file system to have each process read the dictionary file.
This would not work if the FS is not shared among all nodes of the cluster.
I just simply do not want to send a list of 479,623 words to each node.
Note that I did read the password file in one of the processes (rank==0) and send it to the all the other processes. Just because I can :).
So lets crack our shadow files!!!
Python, http://www.python.org
MPI4py, http://mpi4py.scipy.org/
John the Ripper, http://www.openwall.com/john/