
Thanks to the Geneva Application Security Forum, I'm now a proud owner of a Yubikey. This small USB token acts as an OTP (One-Time Password) generator. I'll present you a quick solution to use it within OpenSSH for Two-Factor (T-FA) authentication.
An authentication factor is a piece of information and process used to authenticate or verify the identity of a person or other entity requesting access under security constraints. Two-factor authentication (T-FA) or (2FA) is a system wherein two different factors are used in conjunction to authenticate. Using two factors as opposed to one factor generally delivers a higher level of authentication assurance. Two-factor authentication typically is a signing-on process where a person proves his or her identity with two of the three methods: "something you know" (e.g., password or PIN), "something you have" (e.g.,smartcard or token), or "something you are" (e.g., fingerprint or iris scan).
A Yubikey is a small USB HID device which is seen as a generic keyboard (no driver needed) with a small button. Each time the button is pressed it generates a one-time password secured using AES-128 encryption and ModHex encoding. For more details, you can have a look at this detailed article.
There is various solutions available, one of them is to use the
a PAM module, but it's still in development and users reports some
crashes, so it doesn't sound a very good solution to me at this
time.
The other solution (the one I'll present in this article) was to
develop a script which will be invoked at each login, before giving
a shell to the user, which will check the OTP.
Here is the way my solution works : I've added a group called
"yubikey" on the system. The SSH server will execute the
authentication script for all the members of this group on each
login (this is done using the sshd_config Match directive). The
script will ask the user to generate an OTP using his Yubikey,
check if this key is authorized for this user, parsing
~/.ssh/trusted_yubikeys then proceed to the validation of the
password. If everything is fine the script gives the user his
shell.
Here are all the steps in detail :
Create the group :
$ groupadd yubikey
Add your user inside the group :
$ adduser mon_user yubikey
Specify the trusted keys for this user :
$ cd /home/mon_user/.ssh $ echo "yubikeyid" >> trusted_yubikeys
Create the script in /usr/local/bin/yubikey.sh :
#!/bin/bash # # (c) 2010 Alexandre De Dommelin # # This program is free software. It comes without any warranty, to # the extent permitted by applicable law. You can redistribute it # and/or modify it under the terms of the Do What The Fuck You Want # To Public License, Version 2, as published by Sam Hocevar. See # http://sam.zoy.org/wtfpl/COPYING for more details. # YUBICO_API_ID="XXXX" TRUSTED_KEYS_FILE="$HOME/.ssh/trusted_yubikeys" STD="\\033[0;39m" OK="\\033[1;32m[i]$STD" ERR="\\033[1;31m[e]$STD" ################################################## ## Disconnect clients trying to exit the script ## ################################################## trap disconnect INT disconnect() { sleep 1 kill -9 $PPID exit 1 } echo "" echo "** One-Time Password Validation Step **" echo "" echo -n "Please provide Yubi OTP then enter Ctrl-d: " OTP=`tr -c -d a-z < /dev/tty` KEY_ID=${OTP:0:12} #################################### ## Get user-trusted yubikeys list ## #################################### if [ ! -f $TRUSTED_KEYS_FILE ] then echo -e "$ERR Unable to find trusted keys list" disconnect else TRUSTED_KEYS=`cat $TRUSTED_KEYS_FILE` fi ####################################### ## Iterate through trusted keys list ## ####################################### for trusted in ${TRUSTED_KEYS[@]} do if [ $KEY_ID = $trusted ] then echo -e "$OK Found key in $TRUSTED_KEYS_FILE - validating OTP now ..." if wget "https://api.yubico.com/wsapi/verify?id=$YUBICO_API_ID&otp=$OTP" -O - 2> /dev/null | grep "status=OK" > /dev/null then echo -e "$OK OTP validated" exec `grep "^$(whoami)" /etc/passwd | cut -d ":" -f 7` else echo -e "$ERR Unable to validate generated OTP" > /dev/stderr sleep 1 disconnect fi fi done echo -e "$ERR Key not trusted" > /dev/stderr disconnect
Give it the right permissions :
$ chmod 755 /usr/local/bin/yubikey.sh
Configure /etc/ssh/sshd_config with this parameters :
Match group yubikey
ForceCommand /usr/local/bin/yubikey.sh
Then restart SSH server :
$ /etc/init.d/ssh restart