/etc/shadow format

Recently, I found myself trying to understand what was going on in the shadow file. For one thing, the “password” field in Ubuntu Lucid Lynx is much longer than it is in Red Hat Enterprise Linux 5. Then there were the exclamation points in front of some password entries.

Originally, there was no /etc/shadow file – the passwords and salts were contained with other user information in /etc/passwd. The problem was that /etc/passwd was readable by anyone, and that attacks became more common and more powerful. It was necessary to move the password into a separate file that would only be readable by root.

Here is an example of a shadow file line:

ddouthitt:$6$QR3drPrQ$JLolPKyiVuXvea1F2IpbPx9F9PEV0s/IGcNCpm6ZrBA6AFDvwHPQG7EsTQHuUqxfCvlsuKRb.O7w5RLPyj8nS/:15119:0:99999:7:::

Each field is separated by a colon (:). There are a number of fields:

  1. User name. This must match up with a user name in /etc/passwd; it is the key.
  2. Password. This field is a hash of the password (not the actual password itself) combined with an id (specifying which form of encryption was used) and with a salt.
  3. Last changed date. This is the day that the password was last set (in days since January 1, 1970).
  4. Minimum days. This is the minimum number of days that a password must be active before a password can be changed again. A user’s password cannot be changed by them until this number of days has elapsed.
  5. Maximum days. This is the maximum number of days for a password to be valid. Once the maximum number of days has elapsed, the user is forced to change their password.
  6. Warn days. Before a password expires, warn the user this many days ahead of time.
  7. Inactive days. Once a password has expired, it will be disabled after this many days.
  8. Expire date. On this date (in days since January 1, 1970), the account is disabled and the login can no longer be used.

Rather than trying to compute the date from the number of days since 1970, use the chage command:

$ chage -l ddouthitt
Last password change					: May 25, 2011
Password expires					: never
Password inactive					: never
Account expires						: never
Minimum number of days between password change		: 0
Maximum number of days between password change		: 99999
Number of days of warning before password expires	: 7

This also explains what each number means, and incorporates any defaults.

The password is more complicated. The actual password is not stored anywhere; the stored value in the /etc/shadow file is a hash generated from the password.

Originally, the password hash was just the hash itself; later, a two-character salt was added at the beginning.

The password hash today comes in three parts, separated by dollar signs ($):

  • Id. This identifies the encryption hash method used. A value of 1 denotes MD5; 2 or 2a is Blowfish; 3 is NT Hash; 5 is SHA-256; and 6 is SHA-512.
  • Salt. This is used by the encryption algorithms, and could be up to 16 characters.
  • Hash. The actual “password” (or hash) is last. MD5 uses 22 characters, SHA-256 uses 43, and SHA-512 uses 86.

Picking apart the example password entry above shows this:

  • Id = 6 (SHA-512)
  • Salt = QR3drPrQ
  • Hash = JLolPKyiVuXvea1F2IpbPx9F9PEV0s/IGcNCpm6ZrBA6AFDvwHPQG7EsTQHuUqxfCvlsuKRb.O7w5RLPyj8nS/

Lastly, the password entry could be missing entirely (which means no password) or it could have an invalid entry (locked account).

Traditionally, locking was done with the asterisk (*) by convention or by the word LOCKED. However, this has been extended – by convention – to a variety of new suggestions. System logins that never had a password use a double exclamation mark (!!) and accounts that have been locked have the valid password entry invalidated by a exclamation mark prefix. Using the prefix in this way allows the password to be reinstated as it was.

FreeBSD uses a slightly different setup, with a file called /etc/master.passwd, an extended /etc/passwd file with password aging included, and support for an extended DES format (which starts with an underline). Extended DES is more secure than the original DES, but is no longer used in favor of the new modular format described above. FreeBSD standardizes on MD5 – like Red Hat, and unlike Ubuntu.

By the way – that’s not my real password – so don’t look at it.

Locking out root!

This is not as far fetched as it sounds; every Macintosh OS X system comes configured in this way: it is impossible to log in as root.

How does one do things as root then? I shall reveal the secret…

First of all, one needs to make sure that the program sudo is available and correctly configured. It must be configured to allow you (or the system owner) to switch to root. Best to test this directly before doing anything to the root account.

Once you have verified that you can switch to root using sudo, then it is time to actually lock the root account. Before doing so, open a root shell using sudo or a direct log in as root. Then execute:

# passwd -l root

There! Now no one can log in as root – don’t you feel much better? Well…. you can become root (by using sudo) but logging in directly as root is impossible.

If passwd does not recognize the -l option, then just put an asterisk (*) into the password field, wherever it is. HP-UX, Linux, and Solaris all recognize the -l option; FreeBSD uses the -l option for a different purpose.

For FreeBSD (and quite probably, OpenBSD and NetBSD as well), use the vipw command to lock out not only the root account, but the toor account as well. The toor account is identical to the root account (including userid) but allows user customization.

When combined with the wheel group, this will lock down your root account quite effectively. Just don’t stop there: remember to use multiple defenses. However, that’s a topic for another day.

Update: This is most useful in situations where a normal user will always have access (workstations come to mind).  If your normal users are authenticated via NIS, or Active Directory, or LDAP, don’t do this! If root logins are locked out, and none of the users can log in…….. then what?  Uh oh….