What’s all this about
The benefits of having 2 physically separated factors for authentication needs no introduction. It’s been “recently” popularized by the Google authenticator in particular, which is simple and relatively efficient for Google websites.
Having multiple authentication factors is also a good idea for other sensitive authentication interfaces. Often, your only authentication interface is OpenSSH.
State of authentication methods in OpenSSH
Unfortunately, current versions of OpenSSH require password authentication (keyboard-interactive) to be enabled in order to insert both authentication factors: generally your password, and a one time password - concatenated into one password request field, and split by the authenticator server-side. It therefore did not support public key authentication and password (such as an OTP) at the same time.
Since OpenSSH 6.3, this is no longer true. OpenSSH now supports true multi-factor authentication and will check keys as well as passwords (and other authentication methods). It will only let you login if all the selected authentication methods succeed.
To dive into some more details
When public key authentication is used, password authentication (or/and challenge response authentication, in fact) is bypassed. Even PAM (Pluggable Authentication Module, the modular authentication system used by Linux and some other systems) authentication is bypassed. Only PAM account, session and others are called - not PAM auth. PAM auth is the only part of PAM authentication where text data can be retrieved from the user, as PAM closes stdin (standard input) to prevent any further input.
Older versions of OpenSSH
Starting from Red Hat Enterprise Linux 6.3 and all distributions based on it (CentOS 6.3, Scientific Linux 6.3, for example), OpenSSH is patched to support multiple authentication methods (openssh-5.3p1 release 81.el6_3).
What’s a one time password
One time passwords are passwords which are usable only once, then invalidated. They’re usually generated using a specific algorithm, based on a secret seed value. Both the client and servers are able to compute the current valid OTP (One time password).
There is also a standard, called OATH defining various kinds of OTPs, or one time passwords. Google authenticator, for example, supports this standard and supports both time based and HMAC based OTPs. In fact, many companies support the OATH standard, which is a good thing. It means interoperability between devices which are used to store the OTP secret seeds and generate OTPs for you.
Proper use of the 2nd factor with OTP
Finally, remember that the 2nd factor (the OTP generator and secret seed value) only significantly improve security if stored separately from the first factor (the private key) by the clients. Remember also that reusing the same secret seed value for different services mean that fully compromising one service, gives access to your 2nd factor for all other services as well.
Setting up OpenSSH with OATH
Setting up OATH toolkit
The OATH toolkit is an open-source OATH implementation, which supports TOTP and HOTP. It also supports base32 based OTP seeds (i.e. it’s compatible with Google Authenticator).
This file has to be created. It’s permissions should be set to 0600 and owned by root.
#Format: #[HOTP,HOTP/T - - [last OTP] [date of last use] HOTP/T30 kang - DEADBEEFDEADBEEF 0 783540 2013-02-19T16:52:38L
- In this case, HOTP/T30 is the usual default for OATH authentication. It means time based token, 30 seconds period.
- HTOTP/T implements TOTP. This may be confusing.
- HTOP (without /T) on the other hand is really HTOP.
- The user name is the unix/posix username.
The secret seed value is the secret shared between the system and the user’s authenticator. It must stay confidential as the entire security of the OTP scheme depends on it. In particular, it must never be copied to the device performing the SSH key authentication (as it would defeat the purpose entirely).
The secret seed value should be known by the user and by the server to function. It’s possible to generate a new seed value like this:
Generating the secret value should be done on the server that will host the secret value, or on a secure server and securely transmitted. Seeds are not like password hashes.Once recovered by an attacker, those give the direct capability to generate valid OTPs. This is a design trade-off from the OATH standard.
openssl rand -hex 10
Setting up OpenSSH with public key + OATH
Protocol 2 RequiredAuthentications2 publickey,keyboard-interactive PasswordAuthentication no ChallengeResponseAuthentication yes
These settings allows us to tell OpenSSH to use, in order:
- Public key authentication (publickey), then:
- Challenge Response (or Password) authentication (keyboard-interactive).
The public key authentication is performed as per usual. For the keyboard-interactive authentication, PAM auth is called.
We install a PAM module that support OTPs (I like the GNU OATH Toolkit, but Google Authenticator PAM module also works).
It is important to disable Password authentication in PAM, as otherwise regular password (pam_unix.so or password-auth in general, but your mileage may vary) could be used instead of the OTP module.
#%PAM-1.0 auth required pam_sepermit.so ## Disabled! auth include password-auth auth requisite pam_oath.so usersfile=/etc/users.oath digits=6 window=20 account required pam_nologin.so
The most common client for OTP is again Google Authenticator (which works with the OATH Toolkit as well the Google Authenticator PAM module). It actually adds a little variation to the regular OATH OTPs: the secret seed value is base32 encoded, instead of being hex encoded.
Thankfully, OATH Toolkit can convert those just fine, for example:
$ oathtool -v ebaffebceb2d391d478c Hex secret: ebaffebceb2d391d478c Base32 secret: 5OX75PHLFU4R2R4M [...]
The base32 secret is to be used with the Google Authenticator client and the hex secret can be used with regular OATH clients and with the OATH module used above.
Once the OTP’s secret seed values generated, and the OATH client (here, Google Authenticator) is configured with the same secret seed value, you can enjoy OpenSSH with a proper 2 factors authentication.
Demo: it works! ;)
$ sftp insecure.ws Authenticated with partial success. One-time password (OATH) for `kang':
- After “Authenticated with partial success.” the user is authenticated via the SSH key authentication.
- The user is then prompted for for it’s OTP via SSH’s ChallengeResponseAuthentication and PAM.
- After entering a valid 6 digits (default) OTP, the user is logged in.