Hacking - The Art of Exploitation, 2nd Edition

(Romina) #1
Cryptology 419

reader@hacking:~/booksrc $ gcc -o crypt_test crypt_test.c
/tmp/cccrSvYU.o: In function main': crypt_test.c:(.text+0x73): undefined reference tocrypt'
collect2: ld returned 1 exit status
reader@hacking:~/booksrc $ gcc -o crypt_test crypt_test.c -l crypt
reader@hacking:~/booksrc $ ./crypt_test testing je
password "testing" with salt "je" hashes to ==> jeLu9ckBgvgX.
reader@hacking:~/booksrc $ ./crypt_test test je
password "test" with salt "je" hashes to ==> jeHEAX1m66RV.
reader@hacking:~/booksrc $ ./crypt_test test xy
password "test" with salt "xy" hashes to ==> xyVSuHLjceD92
reader@hacking:~/booksrc $


Notice that in the last two runs, the same password is encrypted, but


using different salt values. The salt value is used to perturb the algorithm


further, so there can be multiple hash values for the same plaintext value if


different salt values are used. The hash value (including the prepended salt)
is stored in the password file under the premise that if an attacker were to


steal the password file, the hashes would be useless.


When a legitimate user needs to authenticate using the password hash,


that user’s hash is looked up in the password file. The user is prompted to


enter her password, the original salt value is extracted from the password file,


and whatever the user types is sent through the same one-way hash function


with the salt value. If the correct password was entered, the one-way hashing


function will produce the same hash output as is stored in the password file.


This allows authentication to function as expected, without ever having to


store the plaintext password.


0x761 Dictionary Attacks


It turns out, however, that the encrypted passwords in the password file aren’t


so useless after all. Sure, it’s mathematically impossible to reverse the hash,


but it is possible to just quickly hash every word in a dictionary, using the salt


value for a specific hash, and then compare the result with that hash. If the


hashes match, then that word from the dictionary must be the plaintext


password.


A simple dictionary attack program can be whipped up fairly easily. It just


needs to read words from a file, hash each one using the proper salt value,


and display the word if there is a match. The following source code does this


using filestream functions, which are included with stdio.h. These functions


are easier to work with, since they wrap up the messiness of open() calls and


file descriptors, using FILE structure pointers, instead. In the source below,


the fopen() call’s r argument tells it to open the file for reading. It returns


NULL on failure, or a pointer to the open filestream. The fgets() call gets


a string from the filestream, up to a maximum length or when it reaches the


end of a line. In this case, it’s used to read each line from the word-list file.


This function also returns NULL on failure, which is used to detect then


end of the file.

Free download pdf