Playing with shadow(s)
The passwords are stored in a digital fingerprint using salt (salted hash) in the Linux system through the crypt function. You can find relevant information about the implementation in Ubuntu at http://manpages.ubuntu.com/manpages/bionic/man3/crypt.3.html (how to call this function, what the arguments are etc.) Assume that you have managed to access a secret shadow file of an Ubuntu Linux system (see the shadow file contents below). The system has two users, bob and alice.
alice:$6$.s6xaWmE$m9KjrSJ1dgZ20M5IhEyXORNV.KZwBk5hp1XZ0mpOyTe.dGET.EdMCFgPimkeM7nWEW4wejMoVV.40Cg6w9XJ..:17470:0:99999:7::: bob:$6$aACNZdTj$GYrSPRP.ieCiUfmFFRwKwEByU2rdSdfP4gCij1asUgT.dpmmu3NIDLAAde5cfvNtacI9JUGQUgrBciUWAUWNY1:17470:0:99999:7:::
Tasks
Based on the information you will obtain from the above link, which hash function did the system use to generate the salted hashed passwords?
From the documentation, we get the following information:
The glibc2 version of this function supports additional encryption algorithms. If salt is a character string starting with the characters "$id$" followed by a string optionally terminated by "$", then the result has the form: $id$salt$encrypted id identifies the encryption method used instead of DES and this then determines how the rest of the password string is interpreted. The following values of id are supported: ID | Method ───────────────────────────────────────────────────────── 1 | MD5 2a | Blowfish (not in mainline glibc; added in some | Linux distributions) 5 | SHA-256 (since glibc 2.7) 6 | SHA-512 (since glibc 2.7)
We can see in both lines of our shadow file, that between the first and second colon (:
) the hashed value is following the format described above. This means that the id of the function used is between the first and second dollar sign ($
) and that value is in both cases the value 6. From this result, we know that SHA-512
was used.
Which salt was used for bob and which for alice?
The salt that was used for bob is
.s6xaWmE
and the salt for aliceaACNZdTj
. We get this data on each line, between the second dollar sign ($
) and the third.
From the shadow file, can you see for sure if alice and bob have chosen different passwords? Explain your answer.
Since the system used different salt while hashing each password, we cannot infer any information regarding the similarity of the passwords of bob and alice.
Your goal is to discover the passwords of these two users. To do this, you have some information about the personal life of bob and alice:
For the bob user, you know that he is now starting to learn how to use computers. He is unaware of security risks and has probably chosen an easy password (one that many users generally select).
For alice, you know some of her personal information: her phone number is 6955345671, her license plate is ZKA4221, and she likes the Rolling Stones. Alice has only a limited knowledge of security. She knows it is suitable for a password to combine letters with numbers and have several characters. Still, she does not fully understand how to choose a secure password.
Please describe the actions you will take to guess their passwords, doing your tests on the shadow file. For bob, use lists of common passwords, while for alice, use the above personal information.
To get the password of bob, we used a simple approach using John the Ripper (lovely tool by the way). As seen in the following commands, we installed John the Ripper and using the default settings we asked John to crack any passwords in our shadow file.
sudo snap install john-the-ripper;
john shadow ;
IIn seconds, John the Ripper produced the password for the user bob, which was 1234567890. John the Ripper was so quick that it felt like magic! Unfortunately (or fortunately, depending on the context), John the Ripper cannot do magic… The reason it was so fast, in this case, is because the default settings for John the Ripper instruct the tool to try many simple passwords first using wordlist files. We already knew that bob was using one of those passwords, so it made the selection of options trivial.
At this stage, it would appear that the password for alice was harder to guess, and John the Ripper did not produce a result after we let it execute for a few minutes. Something that is worth mentioning about the case of bob is the following; We could have asked John the Ripper to try and crack the password using all alphanumeric characters only ([a-z][A-Z][0-9]). It would have taken longer, but it could work since we knew from Human Intelligence (HumInt) that bob is using fairly simple passwords.
Below is the raw output of the console for the case of cracking the password of bob. Please note that we used ctrl+c
to kill the execution as we did not expect John the Ripper to get the password for alice as well.
$ john shadow Created directory: /home/bob/snap/john-the-ripper/459/.john Warning: detected hash type "sha512crypt", but the string is also recognized as "HMAC-SHA256" Use the "--format=HMAC-SHA256" option to force loading these as that type instead Warning: detected hash type "sha512crypt", but the string is also recognized as "sha512crypt-opencl" Use the "--format=sha512crypt-opencl" option to force loading these as that type instead Using default input encoding: UTF-8 Loaded 2 password hashes with 2 different salts (sha512crypt, crypt(3) $6$ [SHA512 256/256 AVX2 4x]) Cost 1 (iteration count) is 5000 for all loaded hashes Will run 12 OpenMP threads Proceeding with single, rules:Single Press 'q' or Ctrl-C to abort, almost any other key for status Warning: Only 46 candidates buffered for the current salt, minimum 48 needed for performance. Warning: Only 45 candidates buffered for the current salt, minimum 48 needed for performance. Almost done: Processing the remaining buffered candidate passwords, if any. Warning: Only 43 candidates buffered for the current salt, minimum 48 needed for performance. Warning: Only 33 candidates buffered for the current salt, minimum 48 needed for performance. Proceeding with wordlist:/snap/john-the-ripper/current/run/password.lst, rules:Wordlist 1234567890 (bob) Proceeding with incremental:ASCII
To tackle the case of alice, we had to improvise a bit. First of all, we made a text file that on each line it contained the personal information that Human Intelligence gathered for us about alice. To ensure that John the Ripper would have more material to work with, we also did some variations to some data, like splitting the license plate into two tokens. The file (keywords.lst
) looked like so:
6955345671 ZKΑ4221 Rolling Stones alice zka4221 zka 4221 Stones Rolling
Then, we used hashcat
to create a new list that would combine the previous tokens making more complex passwords. We had this hint from the Human Intelligence analysis, so it was an easy choice to make. The new and amazing list (advanced.lst
) that we created had the following data in it:
sudo apt-get install hashcat;
#Type in the contents of the list above
nano keywords.lst;
#Not sure why it requires sudo
sudo hashcat -a 1 --stdout keywords.lst keywords.lst > advanced.lst;
69553456716955345671 6955345671ZKΑ4221 6955345671Rolling Stones 6955345671alice 6955345671zka4221 6955345671zka 69553456714221 6955345671Stones 6955345671Rolling ZKΑ42216955345671 ZKΑ4221ZKΑ4221 ZKΑ4221Rolling Stones ZKΑ4221alice ZKΑ4221zka4221 ZKΑ4221zka ZKΑ42214221 ZKΑ4221Stones ZKΑ4221Rolling Rolling Stones6955345671 Rolling StonesZKΑ4221 Rolling StonesRolling Stones Rolling Stonesalice Rolling Stoneszka4221 Rolling Stoneszka Rolling Stones4221 Rolling StonesStones Rolling StonesRolling alice6955345671 aliceZKΑ4221 aliceRolling Stones alicealice alicezka4221 alicezka alice4221 aliceStones aliceRolling zka42216955345671 zka4221ZKΑ4221 zka4221Rolling Stones zka4221alice zka4221zka4221 zka4221zka zka42214221 zka4221Stones zka4221Rolling zka6955345671 zkaZKΑ4221 zkaRolling Stones zkaalice zkazka4221 zkazka zka4221 zkaStones zkaRolling 42216955345671 4221ZKΑ4221 4221Rolling Stones 4221alice 4221zka4221 4221zka 42214221 4221Stones 4221Rolling Stones6955345671 StonesZKΑ4221 StonesRolling Stones Stonesalice Stoneszka4221 Stoneszka Stones4221 StonesStones StonesRolling Rolling6955345671 RollingZKΑ4221 RollingRolling Stones Rollingalice Rollingzka4221 Rollingzka Rolling4221 RollingStones RollingRolling
To use the above custom wordlist on the shadow file, we issued the following command to John the Ripper:
john --wordlist=advanced.lst --rules shadow;
A few moments later, John the Ripper produced the following output indicating that the password for alice was rollingstones4221
.
$ john --wordlist=advanced.lst --rules shadow Warning: detected hash type "sha512crypt", but the string is also recognized as "HMAC-SHA256" Use the "--format=HMAC-SHA256" option to force loading these as that type instead Warning: detected hash type "sha512crypt", but the string is also recognized as "sha512crypt-opencl" Use the "--format=sha512crypt-opencl" option to force loading these as that type instead Using default input encoding: UTF-8 Loaded 2 password hashes with 2 different salts (sha512crypt, crypt(3) $6$ [SHA512 256/256 AVX2 4x]) Remaining 1 password hash Cost 1 (iteration count) is 5000 for all loaded hashes Will run 12 OpenMP threads Press 'q' or Ctrl-C to abort, almost any other key for status rollingstones4221 (alice) 1g 0:00:00:00 DONE (2021-11-26 17:09) 3.846g/s 3765p/s 3765c/s 3765C/s 69553456716955345671..Rollingstonesing Use the "--show" option to display all of the cracked passwords reliably Session completed
Bonus Material
Finding previously cracked passwords
A tip for people that are new to John the Ripper. In case you forgot to write down all passwords that were produced; you can issue the following command that will show you all the passwords that John the Ripper knows for the specific input file:
john --show shadow;
$ john --show shadow alice:rollingstones4221:17470:0:99999:7::: bob:1234567890:17470:0:99999:7::: 2 password hashes cracked, 0 left
Trying to crack a shadow file using Python
In case you would like to use programming and manually crack the shadow file, there are ways.
Using the Python language and the crypt package, we can write a simple program. The program will accept the salt and the unencrypted input text and produce the hashed output. It would be the same result; as a result, a Linux machine would make while creating its shadow file.
import crypt
from hmac import compare_digest as compare_hash
crypt.crypt("1234567890", "$6$aACNZdTj$")
#It would produce the following, which is the salted hash for the password of bob
#'$6$aACNZdTj$GYrSPRP.ieCiUfmFFRwKwEByU2rdSdfP4gCij1asUgT.dpmmu3NIDLAAde5cfvNtacI9JUGQUgrBciUWAUWNY1'