Implementation

Solaris uses the /etc/ file to keep track of every user on the system. As we have seen in the previous unit, the /etc/passwd file contains the username, the real name, identification information, and basic account information for each user. What the password file does not contain is the encrypted user password. That is stored in the /etc/shadow file.

Encrypted Password System

When Solaris requests your password, it needs some way of determining that the password that you type is the correct one. Under normal circumstances, most systems protect the so that they could be accessed only by privileged users and utilities. However, through accident, programming error, or deliberate act, the contents of the password file could occasionally become available to unprivileged users.

In previous computer systems, passwords were stored in plain text where the file was appropriately restricted. The real danger posed by such systems explained Morris and Thompson is not that software problems might someday cause a problem, but that humans might accidently expose the passwords for the world to see.

UNIX avoids this problem by not keeping actual passwords anywhere on the system. Instead UNIX stores a value that is generated by using the password to encrypt a block of zero bits with a one-way function called (). The results of the calculation were traditionally stored in the /etc/passwd file. Solaris stores that information in the /etc/shadow file. When you try to log in to an account, the program /bin/login does not decrypt the stored password. Instead /bin/login takes the password that you typed, uses it to transform another block of zeros, and compares the newly transformed block with the block stored in the /etc/passwd file. If the two encrypted results match, the system lets you in.

The security of this approach rests upon the strength of the encryption algorithm and the difficulty of guessing the user’s password. To date, the crypt() algorithm and its successors have proven highly resistant to attacks.

The Traditional crypt() Algorithm

The algorithm that traditional crypt() uses is based on the Data Encryption Standard (DES) of the National Institute of Standards and Technology (NIST). In normal operation, DES uses a 56-bit key (8 7-bit ASCII characters) to encrypt blocks of original text, or clear text, that are 64 bits in length. The resulting 64-bit blocks of encrypted text, or ciphertext, cannot be decrypted to the original cleartext without knowing the original 56-bit key.

The UNIX crypt() function takes the user’s password as the encryption key and uses it to encrypt a 64-bit block of zeros. The resulting 64-bit block of ciphertext is then encrypted again with the user’s password. The process is repeated a total of 25 times. The final 64 bits are unpacked into a string of 11 printable characters that are stored in the shadow password file. Each of the 11 characters holds six bits of the results, represented as one of 64 characters in the set “.”, “/”, 0-9, A-Z, a-z, in that order. Thus the value 0 is represented as “.”, and the value 32 is the letter “U”. Note: Do not confuse the crypt() algorithm with the crypt encryption program. The crypt program uses a different encryption system from the crypt() algorithm.

Although the source code to crypt() is readily available, no technique has been discovered or publicized to translate the encrypted password back into the original password. Such reverse translation may not even be possible. As a result, the only known way to defeat UNIX password security is via a brute-force attack, or by a dictionary attack. A dictionary attack is conducted by choosing likely passwords from a dictionary, encrypting them, and comparing the results with the value stored in /etc/shadow. This approach to breaking a cryptographic cipher is also called a key search or password cracking. It is made easier by the fact that DES uses only the first eight characters of the password as its key. Dictionaries need only contain passwords of eight characters or fewer.

Robert Morris and Ken Thompson designed crypt() to make a key search computationally expensive. The idea was to make dictionary attacks take too long to be practical. At the time, software implementations of DES were quite slow. Iterating the encryption process 25 times made the process of encrypting a single password 25 times slower still. On the original PDP-11 processors upon which UNIX was designed, nearly a full second of computer time was required to encrypt a single password. To eliminate the possibility of using DES hardware encryption chips, which were a thousand times faster than software running on a PDP- 11, Morris and Thompson modified the DES tables used by their software implementation, rendering the decryption chips and their program incompatible. The same modification also served to prevent a bad guy from simply pre-encrypting an entire dictionary and storing it.

UNIX Salt

What was the modification made by Morris and Thompson? They added a bit of salt. Just as table salt adds zest to grits, the salt that Morris and Thompson sprinkled into the DES algorithm added a little more spice and variety. The DES salt is a 12-bit number, between 0 and 4095, which slightly changes the results of the DES function. Each of the 4096 different salts makes a password encrypt in a different way.

When you change your password, the /bin/passwd program selects a salt based on the time of day. The salt is converted into a two-character string and is stored in the /etc/shadow file along with the encrypted password. In this manner when you type your password at login time, the same salt is used again. UNIX stores the salt as the first two characters of the encrypted password.

Let’s consider the following entries from the /etc/shadow file on my Solaris system:

sam:cdUIOkjWJxzA2:15012:::::: sally:1lJCoa/mnLkA6:15012:::::: alice:ZfbUsVQmAKDCM:15012:::::: bob:v7RcCe3X4sNHo:15012::::::

Do they have the same password?

What is/are their passwords?

In recent years the security provided by the salt has diminished significantly. Having a salt means that the same password can be encrypted in 4096 different ways. This makes it much harder for an attacker to build a reverse dictionary for translated encrypted passwords back into their encrypted form. To build a reverse dictionary of 100,000 words, an attacker would need to have 409,600,000 entries. But with 8-character passwords and 13-character encrypted passwords, 409,600,000 entries fit in roughly 8 GBs of storage.

Another problem with the salt was an error in implementation: many systems selected which salt to use based on the time of day which made some salts more likely than others. crypt(), DES Extended, Modular Crypt Format

Several UNIX systems have improved the security of the crypt() function by changing the underlying encryption algorithm. Instead of a modified DES algorithm, a variety of other algorithms have been adopted, including Blowfish and MD5. The advantage of these new algorithms is that more characters of the password are significant, and there are many more possible values for the salt. Both of these changes significantly improve the strength of the underlying encrypted password system. The disadvantage is that the encrypted passwords on these systems will not be compatible with the encrypted passwords on other systems.

The Modular Crypt Format (MCF) specifies an extensible scheme for formatting encrypted passwords. MCF is one of the most popular formats for encrypted passwords around today. For example

student:$1$mVR1ETu7$/J9SnIZIenedarqK7g1hH/:14491:0:99999:7:::

Dollar signs ($) are used to delimit the MCF fields where

Field Purpose Notes

1 Specifies encryption algorithm 1 specifies MD5 2 specifies Blowfish

2 Salt Limited to 16 characters

3 Encrypted password Does not include salt, unlike traditional UNIX crypt() function

Below are the same four users and their password(s) on a different UNIX system

sam:$1$Qw8/Nxz3$x5Elrx6Ho6Iu9P5Vc2StV0:15012:0:99999:7::: sally:$1$IbLyt4w7$d6QaGLihoRLoOh43UG/vZ0:15012:0:99999:7::: alice:$1$B8RsSahC$62PxTDafefARmLa0n5r51/:15012:0:99999:7::: bob:$1$pDSBD3F2$Ub3SY.b7B7WhiwvOakMnX.:15012:0:99999:7:::

Do they have the same password?

What is/are their passwords?

Protecting Passwords

As the name implies, a shadow password file is a secondary password file that shadows the primary password file. On Solaris the shadow password file is stored in the file /etc/shadow and contains the encrypted password and a password expiration date. The /etc/shadow file is protected so that it can be read only by the superuser. Thus, an attacker cannot obtain a copy to use in verifying guesses of passwords.

Protecting the System

Although changes to the encrypted password system have improved the security of encrypted passwords, they have failed to fundamentally address the weakness exploited by password crackers. People pick passwords that are easy to guess! If an attacker can obtain a copy of the password file, it is a simple matter to guess passwords: perform the encryption transform and compare against the shadow file. The best way to deal with the problem of poorly-chosen passwords is to eliminate reusable passwords entirely by using one-time passwords, some form of biometrics, or a token-based authentication system. Such systems can be awkward or expensive.