2FA SSH aka OpenSSH OATH, Two-Factor Authentication
Good security is based on layers of protection. At some point the usability gets in the way. My thread model on accessing systems is to create a different ssh pair of keys (private/public) and only use them instead of a login password. I try to keep my digital assets separated and not all of them under the same basket. My laptop is encrypted and I dont run any services on it, but even then a bad actor can always find a way.
Back in the days, I was looking on Barada/Gort. Barada is an implementation of HOTP: An HMAC-Based One-Time Password Algorithm and Gort is the android app you can install to your mobile and connect to barada. Both of these application have not been updated since 2013/2014 and Gort is even removed from f-droid!
Talking with friends on our upcoming trip to 34C4, discussing some security subjects, I thought it was time to review my previous inquiry on ssh-2FA. Most of my friends are using yubikeys. I would love to try some, but at this time I dont have the time to order/test/apply to my machines. To reduce any risk, the idea of combining a bastion/jump-host server with 2FA seemed to be an easy and affordable solution.
OpenSSH with OATH
As ssh login is based on PAM (Pluggable Authentication Modules), we can use Gnu OATH Toolkit. OATH stands for Open Authentication and it is an open standard. In a nutshell, we add a new authorization step that we can verify our login via our mobile device.
Below are my personal notes on how to setup oath-toolkit, oath-pam and how to synchronize it against your android device. These are based on centos 6.9
We need to install the epel repository:
# yum -y install https://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
Searching for oath
# yum search oath
the results are similar to these:
liboath.x86_64 : Library for OATH handling liboath-devel.x86_64 : Development files for liboath liboath-doc.noarch : Documentation files for liboath pam_oath.x86_64 : A PAM module for pluggable login authentication for OATH gen-oath-safe.noarch : Script for generating HOTP/TOTP keys (and QR code) oathtool.x86_64 : A command line tool for generating and validating OTPs
We need to install three packages:
- pam_oath is the PAM for OATH
- oathtool is the gnu oath-toolkit
- gen-oath-safe is the program that we will use to sync our mobile device with our system
# yum -y install pam_oath oathtool gen-oath-safe
Before we continue with our setup, I believe now is the time to install FreeOTP
FreeOTP looks like:
Now, it is time to generate and sync our 2FA, using HOTP
You should replace username with your USER_NAME !
# gen-oath-safe username HOTP
and scan the QR with FreeOTP
You can see in the top a new entry!
Do not forget to save your HOTP key (hex) to the gnu oath-toolkit user file.
Key in Hex: e9379dd63ec367ee5c378a7c6515af01cf650c89
# echo "HOTP username - e9379dd63ec367ee5c378a7c6515af01cf650c89" > /etc/liboath/oathuserfile
# cat /etc/liboath/oathuserfile
HOTP username - e9379dd63ec367ee5c378a7c6515af01cf650c89
The penultimate step is to setup our ssh login with the PAM oath library.
# ls -l /usr/lib64/security/pam_oath.so
-rwxr-xr-x 1 root root 11304 Nov 11 2014 /usr/lib64/security/pam_oath.so
# cat /etc/pam.d/sshd
In modern systems, the sshd pam configuration file seems:
#%PAM-1.0 auth required pam_sepermit.so auth include password-auth account required pam_nologin.so account include password-auth password include password-auth # pam_selinux.so close should be the first session rule session required pam_selinux.so close session required pam_loginuid.so # pam_selinux.so open should only be followed by sessions to be executed in the user context session required pam_selinux.so open env_params session required pam_namespace.so session optional pam_keyinit.so force revoke session include password-auth
We need one line in the top of the file.
I use something like this:
auth sufficient /usr/lib64/security/pam_oath.so debug usersfile=/etc/liboath/oathuserfile window=5 digits=6
Depending on your policy and thread model, you can switch sufficient to requisite , you can remove debug option. In the third field, you can try typing just the pam_path.so without the full path and you can change the window to something else:
auth requisite pam_oath.so usersfile=/etc/liboath/oathuserfile window=10 digits=6
In every change/test remember to restart your ssh daemon:
# service sshd restart
Stopping sshd: [ OK ] Starting sshd: [ OK ]
If you are getting some weird messages, try to change the status of selinux to permissive and try again. If the selinux is the issue, you have to review selinux audit logs and add/fix any selinux policies/modules so that your system can work properly.
# getenforce Enforcing # setenforce 0 # getenforce Permissive
The last and most important thing, is to test it !
- 34C3 - https://events.ccc.de/congress/2017/wiki/index.php/Main_Page
- HOTP - https://tools.ietf.org/html/rfc4226
- OATH - https://openauthentication.org/
- FreeOTP - https://freeotp.github.io
- Gnu OATH ToolKit - http://www.nongnu.org/oath-toolkit/index.html
- PAM - https://www.linux.com/news/understanding-pam
The idea of using OATH & FreeOTP can also be applied to login into your laptop as PAM is the basic authentication framework on a linux machine. You can use OATH in every service that can authenticate it self through PAM.