June 11, 2010

Weekend Project: One-Time Passwords for Extra Linux Security


Do you take your security extra seriously? Do you reject all unencrypted email and use a 15,360-bit RSA key when you log in over SSH? Well that's pretty good, but it still doesn't protect you from every kind of attack.

Consider this: OpenSSH may create a secure communications channel between your Linux box at home and the PC in the Internet cafe, but some "evildoer" could still install a keystroke-logger that records your password as you type it -- or simply glance over your shoulder. To foil that plot, you need a password that is only good for a single login attempt. Luckily, Linux supports one-time-password schemes through the standard Pluggable Authentication Modules (PAM) framework. All you need to set it up is a little time, a command line, and a printer (cloak and dagger optional).

There are actually two one-time-password packages readily available for Linux. Both follow the same general scheme. First you compute a list of passwords in advance on the machine in question. The user prints out a physical copy of the list, but it is not stored on the machine; only a distinct "verification code" of one form or another is saved on disk, preventing thieves from grabbing the passwords locally. When the user logs in, the login process issues a challenge that only has one correct response from the list. If the user responds correctly, he or she is logged in, and the password used is marked off, never to be deemed valid again.

The Alternatives Compared

The older system is called OPIE, which stands for One-time Passwords In Everything. OPIE uses the S/KEY algorithm (RFC 1760) invented by Leslie Lamport (of LaTeX fame) while at Bellcore in the 1980s. In the preparation stage, OPIE generates a list of passwords each of which consists of a series of common short words, such as OUST COAT FOAL MUG BEAK TOTE. The list has the property that each nth password is a hash of password (n -1). The first password on the list is stored on the computer and scratched off of the user's list; on each subsequent login, the user enters the next password, the computer hashes the password it has saved locally, and if they match, the login is successful and the new password is saved locally in place of the old.

OTPW (for One Time PassWord) is the newer system, and it improves on OPIE in a few key areas.  First, the passwords are used randomly, not sequentially, which makes analysis harder. Second, OTPW uses random strings instead of short, common words, making the passwords much more difficult for an attacker to memorize off the list at a glance. Third, the printed list of passwords is combined with a memorized password known only to the user, which makes the list useless on its own. Finally, the system includes built-in measures to thwart an attacker that logs keystrokes and attempts to duplicate the login session by replaying it before the user has a chance to hit "ENTER."


You can download the latest source from OTPW creator Markus Kuhn's Web site. Your distro may include a package, but most that do seem to stop at the 1.3 release -- the "snapshot" package available at Kuhn's site adds several new features, and is internally called 1.4, even though an official release has not been announced.

You will need to install the development packages for PAM in order to compile OTPW, but it has no other special dependencies. Just unzip the archive, run make and make install.

The package provides two utilities: a PAM module named pam_otpw, and a password generation tool called otpw-gen. Linux distributions that package OTPW (such as Debian) tend to split these up into two separate packages, otpw-bin for the password-generation tool, and pam-otpw for the PAM module. If you are installing through a package management system, install both.


You generate passwords by running otpw-gen at the command line. The program asks you to select a "prefix password" -- the reusable secret portion that you memorize -- then prints out an ASCII-formatted list of numbered passwords to stdout. By default, otpw-gen creates 60 lines' worth of passwords; this is designed to fit nicely onto a sheet of A4 paper. You can specify a different number of lines and columns by adding the -h and -w switches at the command line; how many fits on a page could take some trial and error. There is a maximum of 1000 passwords at a time, though, because OTPW uses three-digit numbers in its list.

The passwords on the list are generated using random entropy from the system -- gathered from the clock, system file access times, and other unpredictable sources. In the list, each password has its own number, followed by the eight-character password itself. Each is actually a base64-encoding of a binary string, but to avoid ambiguity, the difficult-to-read characters "0" (zero), "1" (one), and "l" (lowercase L) are replaced by punctuation.  For example:

001 ase4 5=XK
002 m8Hm G:fQ
003 rF6z iDhC
042 Sf9r 3NgY

The idea is that you should print this list out on paper -- immediately -- and never, ever store it anywhere on the computer. Carry with you at all times, never let it leave your sight, and you will be in good shape.

When the list is generated, otpw-gen also creates a file called .otpw in the user's home directory; each line inside it lists a password number followed by the RIPEMD-160hash of the actual password and the user's secret (never stored or printed) password. That makes the .otpw file crack-proof on its own, and because it is stored in the user's home directory, no system-wide state is required. Whenever a password is used, the OTPW system blanks out the appropriate line in ~/.otpw

To start using OTPW for login, you will need to edit the PAM configuration file of the service you wish to secure. In most cases, this will be SSH, so open (as root) the /etc/pam.d/sshd file. The relevant lines begin with "auth" (which determines which authentication module will be used when accessing the SSH service), and and "session," (which specify other actions the system needs to take at login time).

Comment out the old "auth" line, and add the following:

auth required pam_otpw.so

Below that, add the following line:

session required pam_otpw.so

The first line says to launch the OTPW module as the authentication method, and the second runs an OTPW reminder after login telling you how many passwords remain (not running out is very important).

Finally, open the SSH configuration file /etc/ssh/sshd_config and change the value of ChallengeResponseAuthentication to yes. This tells OpenSSH to use PAM for authentication instead of the default key exchange protocol.

On Your Mark, Get Set, Go!

You are now ready to test the OTPW system! Restart SSHd with sudo /etc/init.d/ssh restart, then try to log in (either from a terminal or from another computer; just don't log out of your desktop system entirely in case you need to troubleshoot).

The SSH login prompt asks you first for your username; after you enter it, it will ask you for a specific password by number. Such as:

login: <em>nate</em>
Password 042:

The number OTPW asks about (42) was chosen randomly from among the unused passwords. At the prompt, you enter your secret "password prefix," followed immediately by the characters from password #42 on your printed list (no spaces or Returns between any of them). For example, if the password prefix you selected were mYpAssPORT, you would enter mYpAssPORTSf9r3NgY. OTPW will hash the result, compare it to ~/.otpw, and log you in, blanking out the entry for password 42 in ~/.otpw.

You're in! Mark out line 042 on your password list (or burn it with acid, cut it out and swallow it; whatever makes you feel the most comfortable). When your list is finally exhausted, you can generate a new one, which replaces ~/.otpw entirely, and you can choose a new secret password prefix.

Extra Credit, Extra Paranoia

If you want to see OTPW's hyper-security features in action, try to initiate two login sessions simultaneously. What you'll find is that the second login session is prompted for not one, but three passwords. This is to thwart attackers who try to race you to the finish, sending the password you type in the split second between when you type the last character and when you hit ENTER. First, OTPW recognizes two login attempts to the same account and asks them for different passwords.  Second, if you are the second login attempt, you will notice the prompt asking for three passwords and be alerted that something is amiss.

Naturally, the easiest way to foul up this otherwise industrial-strength security measure is to lose that all-important piece of paper with the numbered password list. Kuhn recommends that you either print it directly from the command line by piping the output of otpw-gen to lpr, or by running it through a PostScript converter. Either way, if you are working in a shared computing environment, don't leave it sitting in the printer tray (that goes double for shared computing environments where the printer doubles as a photocopier). If you're really worried, consider investing in some waterproof and/or tear-proof paper to make sure the printout itself doesn't get damaged. Don't even think about writing your username and password prefix on it, either.

One-time-passwords add a very specific security feature (at the cost of complexity and "paper management") that you probably do not need for everyday usage; but if you so desired, you could hook OTPW into your desktop Linux machine's console login, sudo, or a variety of other PAM-enabled system tools.

Perhaps a more interesting experiment would be to try and find an electronic way to secure the password list -- one that offered the same portability and "air gap" security of the printed variety but is not easily compromised. There are commercial one-time-password systems that use a physical token to generate the password list, but those are just as easy to lose as a sheet of paper. At the other end of the spectrum, of course, you could get a radioactive implant in your arm like Russell Crowe in "A Beautiful Mind" ... although you might have a little trouble debugging that option.