Background
People that use Linux on a daily basis probably are completely oblivious to the actual mechanisms being used to store their passwords safely and securely on a given Linux system. Oh they might guess that their password is stored in the /etc/passwd
file (they’d be wrong by the way) but most probably never even gave it a passing thought. So I thought I’d take the opportunity to shed some light on how Linux systems “stash” your precious password away.
Solution
So if your password isn’t actually stored in the /etc/passwd
file then where does it get stored?
Answer: the /etc/shadow
file.
This file is where all the keys to each user’s account are kept for safe keeping. Obviously only the root user can peer inside this file so all the commands we’ll be dealing with in this post, it should be assumed that you’ll need to either be root, or use sudo
to run.
/etc/shadow
A typical /etc/shadow
entry:
1 |
root:$6$bbmDJwcZHy5bgEDz$kFO.W/T7nUqcszZWl5RglxoDDAcDxevWpHVfN3v3f.Cx2ZeMcn5PX23VvnnkgtNWZf8hYtqsL0pPkZqyj50NY/:14362:0:33333:7::: |
NOTE1: Don’t get too excited, the above isn’t really my entry, I made this one up.
NOTE2: Each field is separated by a colon (:) & we’re only concerned with the first two columns!
dissecting the hash
The key pieces to notice in that line of what looks like gibberish is the following:
- The first column,
root
is the user whom this entry belongs to from the/etc/passwd
file. - The second column,
$6$.....
is essentially the user’s hashed password.
Taking the second column apart further you should start to notice that’s it’s not complete gibberish after all.
For example:
- the first couple of characters,
$6$
, is a mark that tells the system what type of hashing was used to hash the password. - The text between the next set of dollar signs,
$bbmDJwcZHy5bgEDz$
, is the actual salt that was used to hash your password. - Everything else after, is your password + salt hashed using whatever hash function was specified at the beginning, $6$, in our example here.
Specifically if you look at the man page for the crypt command, man 3 crypt
there is a section that discusses what the $6$
notation means:
So $5$salt$encrypted is an SHA-256 encoded password and $6$salt$encrypted is an SHA-512 encoded one.
NOTE: So in our case the password + salt is being hashed using the SHA-512 scheme.
design details
For reference purposes here’s the rest of that excerpt from the crypt man page:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
If salt is a character string starting with the characters "$id$" followed by a string terminated by "$": $id$salt$encrypted then instead of using the DES machine, id identifies the encryption method used 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) So $5$salt$encrypted is an SHA-256 encoded password and $6$salt$encrypted is an SHA-512 encoded one. "salt" stands for the up to 16 characters following "$id$" in the salt. The encrypted part of the password string is the actual computed password. The size of this string is fixed: MD5 | 22 characters SHA-256 | 43 characters SHA-512 | 86 characters The characters in "salt" and "encrypted" are drawn from the set [a–zA–Z0–9./]. In the MD5 and SHA implementations the entire key is significant (instead of only the first 8 bytes in DES). |
Now what?
So by now you’re probably saying to yourself. OK, big deal, my password is hashed with some salt and stored in /etc/shadow
. What else?
generating the hash manually using mkpasswd
For starters you can generate the $6$...
string yourself manually using the mkpasswd
command:
1 2 |
$ mkpasswd -m sha-512 password saltsalt $6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/ |
In the above command we’re specifying that we want to use the SHA-512 hash, our password is the string password and our salt string is saltsalt. As before we can see in our resulting string the following components:
- $6$ – which hash function was used
- saltsalt – the string “saltsalt” was used
- qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/ – password + salt hashed using SHA-512
generating the hash manually using Python
I came across the following nice Python one-liner that effectively does the same thing as the mkpasswd
command discussed above.
1 2 3 |
$ python -c "import crypt, getpass, pwd; \ print crypt.crypt('password', '\$6\$saltsalt\$')" $6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/ |
generating the hash manually using Perl
1 2 |
$ perl -e 'print crypt("password","\$6\$saltsalt\$") . "\n"' $6$saltsalt$qFmFH.bQmmtXzyBY0s9v7Oicd2z4XSIecDzlB5KiA2/jctKu9YterLp8wwnSq.qc.eoxqOmSuNp2xS0ktL3nh/ |
authconfig
Before I wrap up I thought I’d mention one final tool authconfig
that’s included on Red Hat distros such as Fedora, CentOS, and RHEL. This tool allows you to change what hash algorithm is being used on a particular system. The command to change a system to use SHA-512 would be as follows:
1 |
authconfig –passalgo sha512 –update |
See the man page for authconfig
for more details.
conclusions
And with that you are now a little more in the know as to how Linux systems take your password and store them in the /etc/shadow
file.