Building on last month's column on host security, I'm going to meander into an area that has bugged me for some time: those damned eight-character Unix passwords. Linux is burdened with this unsightly legacy, but it's fairly simple to fix, and I describe the problem and the solutions in this column.
Building on last month’s column on host security, I’m going to meander into an area that has bugged me for some time: those damned eight-character Unix passwords. Linux is burdened with this unsightly legacy, but it’s fairly simple to fix, and I describe the problem and the solutions in this column.
The original Unix password scheme was elegant but hasn’t stood the test of time. Today’s machines are capable of cracking them in a matter of hours. The passwords are stored in a file called /etc/passwd, which has a line detailing each account, and which anyone can read.
Each line consists of seven fields, separated by colons, like so:
root:x:0:0:The Big Cheese:
The first field (root) is the name of the account, the second is the password (simply x here, which is not a valid password), then the user ID (each user is given a unique number), the group ID (groups can be listed in the /etc/group file, but the 0 here is the “primary group”), the GECOS field (The Big Cheese), which contains a description of the account, the home directory (/root), and finally the shell the user uses at login.
According to the Jargon file (http://www.ccil.org/jargon), the GECOS field was originally added to interoperate with GECOS (the General Electric Comprehensive Operating System) machines used for print spooling at Bell Labs. It has since evolved to contain the user’s full name and sometimes other relevant details, such as a phone and office number.
The Password Field
The part of the file we are really interested in here is the password field. The password field is encrypted using the crypt() library call, which uses the DES (Data Encryption Standard) algorithm at its core. The crypt() call takes a two-character “salt” string, which alters the algorithm in one of 4,096 possible ways, and an eight-character password. The password gives you a 56-bit key that, along with the two-character salt, is used to encrypt a string of eight zeros. The string ends up being 11 characters long. To this encrypted string you add the two-character salt. All 13 characters are stored in the /etc/passwd file.
There is no way to decrypt a password from this string, but programs don’t need to. Instead, they ask for a password, then use the first two characters of the password string as the salt and feed it to the crypt algorithm. If the result matches the encrypted string stored in /etc/ passwd, then the password is correct.
When a password is created, the salt field is chosen at random. This means that the same password used by two people will probably have a different salt, and hence look nothing alike once encrypted. It also discourages attackers from keeping a list of encrypted common words that they can look for in /etc/passwd.
Unfortunately, there are several programs that take an /etc/passwd file and try to encrypt dictionary words and their variants with the same salt as the passwords, hoping to get a match. Crack and John the Ripper are the most famous. A colleague of mine once ran Crack on a box sent to us by a vendor, and was surprised when it came up with muitrosnoC for one of the accounts. It seemed less miraculous once I realized that the account was described using the wordConsortium in the GECOS field of the password file.
The Shadow Knows
With modern machines and Beowulf clusters, the 7.2 x 1016 possible combinations of passwords is laughable. One technique for securing passwords,which became widespread in the early 1990s, was to remove the passwords from the /etc/passwd file and put them in a file called /etc/shadow, which not everyone could read. This meant that any program that wanted to read the shadow passwords had to run with special permissions. Some programs — screen savers, for example — were never written with security in mind, and it was fairly easy to trick them into showing you the /etc/shadow file.
Shadow passwords are still popular among Unix vendors, and many Linux distributions ship with shadow passwords enabled. One way to tell whether your system is using shadow passwords is to look at the password field in the /etc/passwd file. For example:
The x is where the encrypted password should be. Because x is not a valid encrypted password, there is no way for the user to log into this account unless there is a corresponding entry containing the real password in the /etc/shadow file:
If your /etc/passwd file contains all xpassword fields, and /etc/shadow contains real password fields, you probably have shadow passwords enabled.
The shadow password suite also supports forced expirations of passwords. The 0 and 99999 fields above indicate the minimum and maximum days since the last change on which the user can change the password. The10152 is the last change date, in days since January 1, 1970. The number 7 is the number of days before password expiration to warn users about the upcoming expiration. The warning looks something like this:
stick login: rusty
Warning: your password will
expire in 5 days
The largest downside to using shadow passwords is the pain of modifying all of the programs that require passwords from the appropriate file to use /etc/shadow instead. Implementing other new security mechanisms presents the same difficulty. It would be ideal if all of these programs used a common framework for authentication and other security-related measures, such as checking for weak passwords and printing the message of the day.
Pluggable Authentication Modules
Pluggable Authentication Modules (PAM for short) is one such framework. The Red Hat and Debian distributions ship with PAM and PAM-aware applications. Applications that are PAM-aware simply ask the PAM library to do the tedious work of authentication. By using PAM modules, the administrator controls exactly how authentication happens.
Listing One: A PAM-Aware Application
stick:~$ ldd /bin/login
libcrypt.so.1 => /lib/libcrypt.so.1 (0×40005000)
libpam.so.0 => /lib/libpam.so.0 (0×40032000)
libpam_misc.so.0 => /lib/libpam_misc.so.0
libdl.so.2 => /lib/libdl.so.2 (0x4003d000)
libc.so.6 => /lib/libc.so.6 (0×40040000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2
You may be running PAM without even knowing it, since PAM is usually set up to imitate normal shadow passwords by default: The library is told to use the pam_Unix.so module for authentication, which reads the /etc/shadow file and checks the password as usual. You can usually tell if an application is PAM-aware by checking to see if it uses the PAM library (see Listing One).
You can see from the second line that the login program uses the libpam. so module. So you need to look at the PAM configuration to figure out wherelogin gets its passwords. There should be a file called /etc/ pam.d/login that details exactly what the library will do when login asks for authentication.
A brief look in the /etc/pam.d directory shows that there is one file for each different PAM-using service. A simple example is the /etc/pam.d/ passwd file. Lines beginning with the #character are comments, which are ignored by the PAM library as is the Unix tradition. The /etc/pam.d/passwd file on my system contains one single line:
Password required pam_unix.so
The first column specifies the module type. The password column refers to password management, which is all the passwd program cares about. The most common type of this is auth for normal authentication, which is what the login program uses. The second column tells the PAM library whether the success of this module is vital or not.
You can have any number of lines in the file referring to different modules, and they might all be required (password and fingerprint scan, perhaps). Alternatively, one might be a fallback for the other (say, password or fingerprint scan). The third entry in the line is the PAM module that is called to do the actual authentication. These normally live in the /lib/security/ directory and can be simple (pam_ deny.so, which simply fails every time) or complex (pam_mkhomedir, which sets up a user’s home directory).
Anything after this on the configuration line gets passed to the particular module so you can tweak its behavior. The pam_unix module handles /etc/shadow in the usual way.
A more illustrative example is the /etc/pam.d/login file, which handles things like restricting root logins to the consoles listed in /etc/securetty, disallowing non-root logins if the /etc/ nologin file exists (usually created during shutdown), printing out the message of the day and the last login time once the authentication succeeds, and forcing the user to update expired passwords. Reading the comments in this file is usually a tutorial in itself and is worth doing if you are interested in customizing your systems.
On a sour note, Debian’s xdm (the X-Windows equivalent of the login program) doesn’t support PAM, so if you use xdm to log in, you’re currently out of luck with PAM. The GNOME equivalent of xdm, gdm, supports PAM in its gdm2 release, now in beta.
Both the shadow utilities and the PAM framework let you use long passwords as opposed to the eight-character-maximum monstrosities mandated by the old crypt() system. The change has been a long time coming. With programs such as Crack, eight-character passwords require phenomenal restrictions to be secure: things like short expiration times (change your password every month), compulsory punctuation (pen!), numbers and mixed case (pEn!), not being based on a dictionary word (qEn!), and a minimum of five characters (pqEn!). Making a password harder to remember increases the chances that someone will write it down, which defeats the whole purpose of passwords. The eight-character limit simply had to go.
The most popular alternative is the MD5 sum of the password, mixed with a salt, in the same spirit as the old DES passwords. MD5 (Message Digest number 5, as described in RFC1321) is an algorithm that takes a message of any length (the password in this case), and produces a 128-bit fingerprint of it. There is no known way to produce another message that has the same fingerprint, short of trying about a trillion different messages, so you don’t have to worry about someone cracking it that way any time soon.
The MD5 method allows you to have passwords of almost any length, although other restrictions make it wise to stay under 128 characters. Best of all, you can make the transition from eight-character to unlimited-length passwords gradually, by changing
to MD5 passwords automatically as people change passwords with the passwd program.
You can do this by using the MD5_ CRYPT_ENAB entry in /etc/login.defs if you’re not using PAM, or putting md5 at the end of every line beginning with password and containing pam_unix.so in the files of the /etc/ pam.d directory. For me this meant altering only /etc/pam.d/login and /etc/ pam.d/passwd.
I hope that one day soon I can add sH0r7 pAZZwRd$ to my collection of old-time Unix anecdotes.
Paul “Rusty” Russell is now paid by WatchGuard to maintain the current Linux packet filter code and develop cool new GPL networky stuff for the Linux kernel while spending the money WatchGuard sends. He can be reached at email@example.com.