[[!meta title="One-time passwords"]] [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: * [S/Key][] (last activity in 2007) * [OPIE][] (only maintained by Debian?) 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][PAM-SAG] 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][OpenBSD]). 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][deb-fa] 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][]. [OTP]: http://en.wikipedia.org/wiki/One-time_password [RFC 2289]: http://www.ietf.org/rfc/rfc2289.txt [RFC 1938]: http://www.ietf.org/rfc/rfc1938.txt [RFC 1760]: http://www.ietf.org/rfc/rfc1760.txt [OpenSSH]: http://www.openssh.com/ [sshd_config(5)]: http://www.openbsd.org/cgi-bin/man.cgi?query=sshd_config [login.conf(5)]: http://www.openbsd.org/cgi-bin/man.cgi?query=login.conf [PAM]: http://en.wikipedia.org/wiki/Pluggable_Authentication_Modules [S/Key]: http://freshmeat.net/projects/pam_skey/ [OPIE]: http://packages.debian.org/lenny/libpam-opie [PAM-SAG]: http://www.kernel.org/pub/linux/libs/pam/Linux-PAM-html/sag-configuration-file.html [OpenBSD]: http://www.openbsd.org/faq/faq8.html#SKey [otpCalc]: http://killa.net/infosec/otpCalc/ [OTPGen]: http://marcin.studio4plus.com/en/otpgen/ [jotp]: http://www.cs.umd.edu/~harry/jotp/ [OTPW]: http://www.cl.cam.ac.uk/~mgk25/otpw.html [RFC 4226]: http://www.ietf.org/rfc/rfc4226.txt [inferior?]: http://en.wikipedia.org/wiki/HOTP#Reception [deb-fa]: http://www.debian-administration.org/articles/510 [FreeAuth]: http://freeauth.org/ [SOTP]: http://www.cavecanen.org/cs/projects/pam_sotp/ [[!tag tags/linux]]