OTP is a protocol for generating single-use passwords used for safer authentication than you would get by using a password directly. The system is challenge/response authentication similar to SSH keys, but with the keys and hashes reduced to something you can actually type in in a reasonable amount of time. While not absolutely secure (nothing is), one-time passwords greatly reduces the window of vulnerability compared to using static passwords directly.
For example, suppose you want to log in to one of your machines from a remote, untrusted teminal (e.g. from an internet café). You obviously don't want to load your SSH key on the untrusted terminal, and a keylogger would capture your password if you used it directly. By using a one-time password, the risk is reduced. A keylogger on the untrusted terminal could capture your one-time password and use it to log in either instead of you or as part of a man-in-the-middle attack. However, after that login is terminated, the keylogger can make no further breaches, as they could if they had captured your password itself. This “small window” risk is the same problem faced by sites that send you plain text emails with one-time URLs for registration confirmation, password reminders, etc. (who can't be bothered to use PGP, sigh).
For more information on one-time passwords, take a look at the following standards:
- RFC 2289 (A One-Time Password System, obsoletes RFC 1928)
- RFC 1938 (A One-Time Password System, obsoletes RFC 1760)
- RFC 1760 (The S/KEY One-Time Password System)
Sound good? Alright, how do we setup SSH to accept one-time passwords on Gentoo?
OpenSSH's SSH daemon supports OTP authentication by default. If you have disabled the support, you'll need to restore it by adding
ChallengeResponseAuthentication yes
to /etc/ssh/sshd_config
and running
# /etc/init.d/sshd reload
From the sshd_config(5) man page, having challenge/response
authentication enabled allows all all authentications styles from
login.conf(5). /etc/login.conf
doesn't exist on my Gentoo or
Debian systems, which is, I think, because they use PAM to handle
all the authentication. Tracing through /etc/pam.d/
,
/etc/pam.d/sshd
builds the following auth
chain on my Gentoo
system:
auth required pam_tally2.so onerr=succeed
auth required pam_shells.so
auth required pam_nologin.so
auth required pam_env.so
auth required pam_unix.so try_first_pass likeauth nullok
auth optional pam_permit.so
We need to add an OTP PAM module. There are several, none of which seem to be actively developed:
The S/Key module does, however, have an ebuild in Gentoo's portage tree (significantly patched from upstream), so we'll use that.
My initial idea was to add skey
to USE
and run
# emerge -av --deep --update --newuse @world
but that enabled built-in S/Key handling in app-admin/sudo
and
similar packages. We don't want applications to use S/Key directly,
we want them to use PAM, and PAM should use S/Key. So instead, just
emerge the S/Key PAM module:
# emerge -av sys-auth/pam_skey
which will pull in the sys-auth/skey
package containing binary
tools and the libskey.so
library.
Configure PAM to use the skey
module for all system authentication
by adding a line like:
auth [success=done ignore=ignore auth_err=die default=bad] pam_skey.so
before the pam_unix.so
line in /etc/pam.d/system-auth
. This
allows users to use their one-time password (if configured) and falls
back to their system password if OTPs are not setup or the entered OTP
is invalid. See /usr/share/doc/pam_skey-*/INSTALL.bz2
for details
on this specific case and the PAM System Administrators'
Guide for details on the syntax. Gentoo's pam_skey
has
been patched up a good deal (see
/usr/share/doc/pam_skey-*/README.bz2
), so on other systems, the
procedure may be different (e.g. OpenBSD has the S/Key module
installed by default).
Setup a one-time password chain for a particular user by running
$ skeyinit
Password:
[Adding wking]
Reminder - Only use this method if you are directly connected
or have an encrypted channel. If you are using telnet
or rlogin, exit with no password and use skeyinit -s.
Enter secret password:
Again secret password:
ID wking skey is otp-md5 99 tyr24366
Next login password: RIM CHUG MUSH LOFT SAFE CHAR
there are a number of options you can pass to skeyinit
to customize
the OTP (hash, effected user, etc.).
That configures your server to accept RFC 2289 passwords. On the client side, you'll need a generator to calculate the appropriate response to server challenges. There are a number of choices:
- S/Key (Gentoo: sys-auth/skey) Gentoo's version of the OpenBSD
package contains the command-line
skey
supporting RFC 2289 and RFC 1760. - otpCalc (Gentoo: sys-auth/otpcalc) RFC 2289 and RFC 1760 compliant calculator using GTK+.
- OTPGen RFC 2289 compliant calculator using the Java 2 Micro Edition (most mobil phones).
- jotp RFC 2289? and RFC 1760 compliant calculator using Java with MD4 and MD5 support.
If you don't have a secure client (e.g. cell phone) that will be accessible from the untrusted terminal, you can also print a list of future OTPs and cary the paper on your person.
$ otp-md5 -xn 5 99 tyr24366
Reminder - Do not use this program while logged in via telnet or rlogin.
Enter secret password:
95: WENT FORM GAUL DATA LYLE SIR FA10 A627 37FB 5078
96: DINE RODE SANK LYON SUCH MEAT 735A 275B 5AAE 4972
97: THEE TOUR GOES HULK WORM TROY EA1D D238 4E4F DFE0
98: ELM RUB CULL ANY LIND HOBO 1167 21B5 014A FD32
99: RIM CHUG MUSH LOFT SAFE CHAR 37CC D302 D8BD 56CA
The printed paper is obviously less secure, because it reduces the authentication requirement from something-you-know (secret key) to something-you-have (paper). If that bothers you, take a look at Markus Kuhn's OTPW package, which uses a different algorithm to genrate OTPs that all begin with a secret (memorized) prefix. Kuhn's approach requires a hacker to copy your paper list and log your keystrokes to extract your prefix.
Eventually, your stock of OTPs will run low, and you'll need to use
skeyinit
again to provide a fresh stash.
Besides RFC 2289, there are alternative one-time password generation possibilities. RFC 4226 (HOTP: An HMAC-Based One-Time Password Algorithm) defines a particular (inferior?) one-time password generation alogrithm. This Debian post describes a FreeAuth implementation that uses time-based keys similar to many commercial systems. The SOTP module doesn't specify it's algorithm, but it has the option of using secret prefixes along the lines of OTPW.