Friday, 29 March 2013

Retriving passwords /etc/shadow

Using Python to retrieve passwords from the /etc/shadow file on Backtrack 5R3 as an exercise in improving scripting skills.

Note: This is an educational exercise for those wishing to learning python as part of becoming a security professional in order to improve their skills and enable them to write or modify tools, a key part of any pen testers repertoire. A solution is not giving, however how to get to a working solution is laid out in the notes. By understanding how the shadow password system works, it is possible to write a script to solve the problem.

In the Violent Python book one of the first example is retrieving passwords from the /etc/passwd file and after describing their example it ask if those reading can modify the script to retrieving passwords in the /etc/shadow file, giving the hint that the shadow file uses SHA512 hashing, the functions for which are in the hashlib library. This is a red herring as the hashlib file only outputs either in Hexadecimal or a string containing non-printable ASCII characters, where as the shadow file contains only printable ASCII characters.

First thing is to understand the problem, on backtrack we know the default password is toor for the user root, this enable us to test our script quite easily. However lets us examine a line from the shadow file.

root:$6$1hjjWhtS$Or2xL2Eedes/ajatnSc0gqcxR0ZAJAIoYxqjPlvESDJX.XPXiydBPK7waQkpypcnsb5f7G6h7eVs8jlkHVptD0:15609:0:99999:7:::

We can see it consists of data separated by colons, the meaning of each segment can be found in the /shadow man page.

  • login name
  • encrypted password
  • date of last password change
  • minimum password age
  • maximum password age
  • password warning period
  • password inactivity period
  • account expiration date
  • reserved field

We are only interested in the first two fields.


  • The login name must be a valid account name, which exist on the system.
  • The encrypted password refer to man page on crypt for details on how this string is interpreted.



The encrypted password file consist of a data segmented by the "$" symbol, these fields are
  • Hash method
  • Salt Value
  • Encrypted Password
The hash methods are represented by the following keys
  • $1$ - MD5
  • $5$ - SHA256
  • $6$ - SHA512
In the case of the example above, the fields are
  • username = root
  • hash method = $6$ (SHA512)
  • Salt = 1hjjWhtS
  • Encrypted password = Or2xL2Eedes/ajatnSc0g ..... 6h7eVs8jlkHVptD0
We still don't have enough information to retrieve the password, as the hashing algorithm, if it is SHA256 or SHA512 is repeated a number of times (rounds). We need to know the number of rounds that have been used as this can be changed, the more rounds, the longer it takes to hash the password which is inconvenient to the user but makes it harder for the attacker if they are brute forcing the password.

If we examine the /etc/login.defs file we will find section giving the number of rounds used.

#
# Only used if ENCRYPT_METHOD is set to SHA256 or SHA512.
#
# Define the number of SHA rounds.
# With a lot of rounds, it is more difficult to brute forcing the password.
# But note also that it more CPU resources will be needed to authenticate
# users.
#
# If not specified, the libc will choose the default number of rounds (5000).
# The values must be inside the 1000-999999999 range.
# If only one of the MIN or MAX values is set, then this value will be used.
# If MIN > MAX, the highest value will be used.
#
# SHA_CRYPT_MIN_ROUNDS 5000
# SHA_CRYPT_MAX_ROUNDS 5000


We know have enough information to attempt to write a script to retrieve the password, we can copy the shadow file to a text file "shadow.txt" and we need a dictionary file "dictionary.txt" contain a word per line.

We can read each line of the shadow.txt, parse the line to extract the username, salt and encrypted password. We can combine the salt with the word from our dictionary.txt file and hash the word and compare it to the encrypted password, if it matches we have guessed the password. In order to do this we need the correct hashing library, the hashlib is not suitable, the correct one is Passlib which is not installed by default on Backtrack 5R3 but can easily be added using the following command


easy_install passlib


To use passlib we can send it the guessed word, the salt value and number of rounds to be used, as shown in the following commands to import the hashing routine and call it.

from passlib.hash import sha512_crypt
sha512_crypt.encrypt(word,salt=salt, rounds=5000)

The lib passlib when it produces a hash digest the output consists of a number of fields and uses by default 60,000 rounds.

  • Hash method
  • Number of rounds
  • Salt Value
  • Encrypted Password

An oddity is that when the number of rounds is set to 5000, the number of rounds is not outputted, making it compatible with the shadow file format.

All we need to do is parse the returned line and compare the encrypted value of the guessed word to the value retrieved from the shadow file.

Security point


Changing the default number of rounds to a higher value can considerable delay an attacker and often make tools that use the default value unusable. Assuming 250ms to hash a word using 5000 rounds, changing to 60,000 rounds will increase the time to 3 secs, over a dictionary attack using several thousand words this will dramatically increase the time to try every word.

Learning outcome


Understanding an operating system and how it is configured will help the security professional develop techniques and tools for testing the security posture of the operating system. The exercise in the book was impossible to complete without understanding how the shadow password system was configured.

No comments:

Post a Comment