Protect sudo and su commands with YubiKey
Introduction
Sometimes you would like to have a more secure sudo or su command, especially if you are a developer and often use docker (that you run with root privileges). Solution that will give you a little more peace of mind if you are attacked by some kind of malware with keylogger. Answer to this case is using YubiKey for protecting sudo or su command. In the following article I will show how to setup a configuration in which sudo or su command will need standard password and touch of YubiKey present in USB port.
UPDATE 2025-01-25: Added paragraph "Bonus 3" at the end of article describing how to have PAM configuration regarding YubiKey in separate file and include it in PAM configuration files.
OS used: Debian 12
Software used: libpam-u2f 1.1.0
Hardware used: YubiKey 5 NFC
Source
This article is based on information from Yubico official site: Ubuntu Linux Login Guide - U2F.
Packages installation
Install library for universal 2nd factor (U2F) PAM module:
$ sudo apt install libpam-u2f
Associating YubiKey with user account
- Insert YubiKey and create config file:
$ mkdir -p ~/.config/Yubico && \
pamu2fcfg > ~/.config/Yubico/u2f_keys
-
When YubiKey begins flashing touch its metal contact.
-
Add other keys if you posses more then one. It is recommended to have at least 2 keys in case one will be lost. To add next key run command:
$ pamu2fcfg -n >> ~/.config/Yubico/u2f_keys
-n, --nouser - print only registration information (keyHandle and public key - useful for appending to existing file)
Hardening access to u2f_keys file
In order to prevent user from changing u2f_keys file without root permission move this file to folder /etc/Yubico/. First we will need to create this folder with permissions only for root and than move file.
$ sudo mkdir -m 700 /etc/Yubico && \
sudo mv ~/.config/Yubico/u2f_keys /etc/Yubico/u2f_keys
-m - set folder permissions
Securing sudo or su
Linux PAM module has many commands for permissions and every one of them can by configured in the same way.
| Command | File location |
|---|---|
runuser |
/etc/pam.d/runuser |
runuser -l |
/etc/pam.d/runuser-l |
su |
/etc/pam.d/su |
su -l |
/etc/pam.d/su-l |
sudo |
/etc/pam.d/sudo |
sudo -i |
/etc/pam.d/sudo-i |
Configure the ones you use, mainly it will be:
sudosudo -i
and if you use root account on your system:
susu -l
If you change only sudo and leave sudo -i config file without changes, user can invoke sudo command without YubiKey by using sudo -i.
Info
sudo -i gives you the root environment, i.e. your ~/.bashrc is ignored. When you will run pwd command you will get path /root.
For things to work you need to change PAM config files for sudo and sudo -i by adding following line at the end of files:
$ sudo vim /etc/pam.d/sudo
(...)
auth required pam_u2f.so authfile=/etc/Yubico/u2f_keys cue [cue_prompt=Remember to touch Key]
$ sudo vim /etc/pam.d/sudo-i
(...)
auth required pam_u2f.so authfile=/etc/Yubico/u2f_keys cue [cue_prompt=Remember to touch Key]
cue - display cue text to remember to touch key
[cue_prompt=Remember to touch Key] - your custom cue text, whole instruction must be in square brackets [ ]
Warning
Once you modify /etc/pam.d/sudo and /etc/pam.d/sudo-i you will need YubiKey to authenticate sudo commands. Don't loose your YubiKeys ;)
After modifying files don't close terminal window. Test changes in new terminal window before proceeding - instruction is in the next paragraph.
Tip
If you would loose your YubiKeys than in order to restore authentication without YubiKey you will need to use Live Linux distribution on USB drive (e.g. Debian Live or Ubuntu image) and than remove added line in /etc/pam.d/sudo file.
Testing YubiKey
- Don't close terminal window in which you edited
/etc/pam.d/sudofile. - Remove YubiKey from the computer.
- Open new terminal.
- In new terminal window run:
$ sudo pwd
- In another new terminal window run:
$ sudo -i pwd
- You will be asked for password and even if password is correct authentication will fail because YubiKey is not plugged in.
- Insert YubiKey, repeat command, input password and touch metal contact of YubiKey when it will be flashing.
$ sudo pwd
- In another new terminal window run command, input password and touch metal contact of YubiKey when it will be flashing.
$ sudo -i pwd
- If authentication succeeded and you see command results than your configuration is correct.
Securing graphical user authentication
Graphical applications for user authentication in Debian use polkit. It is an authentication manager to which applications connect with polkit agents (Gnome has its agent, KDE has its agent etc). Example of applications that invoke GUI login are: system updates, changing settings, firewall configuration, GParted for disk partitioning. To make polkit use YubiKey we need to add line in following file:
$ sudo vim /usr/lib/pam.d/polkit-1
(...)
auth required pam_u2f.so authfile=/etc/Yubico/u2f_keys cue [cue_prompt=Remember to touch Key]
After inputting password remember to press blinking metal contact of YubiKey to complete authentication.
YubiKey without password
Only YubiKey
If you don't want to type user password when using sudo and want to login only with YubiKey put auth required ... before line that reads @include common-auth and comment @include common-auth. Similarly change other files that you modified for use with YubiKey.
auth required pam_u2f.so authfile=/etc/Yubico/u2f_keys cue [cue_prompt=Remember to touch Key]
# @include common-auth # this line is commented
(...)
YubiKey as alternative to password
If you don't want to type user password when using sudo and want to use YubiKey as alternative/sufficient authentication then insert auth sufficient instead of auth required. Also put the line before line that reads @include common-auth. Similarly change other files that you modified for use with YubiKey.
auth sufficient pam_u2f.so authfile=/etc/Yubico/u2f_keys cue [cue_prompt=Remember to touch Key]
@include common-auth
(...)
Info
If you don't press YubiKey metal contact for some time (approximately 40 s) then you will be asked for normal password.
Bonus 1 - Securing Linux graphical login with YubiKey
Linux PAM module has commands for different Desktop Environments logins and every one of them can by configured in the same way. On your system may be present only file for your Desktop Environment.
| Login | Desktop Environment | File location |
|---|---|---|
gdm |
Gnome | /etc/pam.d/gdm-password |
sddm |
KDE | /etc/pam.d/sddm |
lightdm |
XFCE | /etc/pam.d/lightdm |
$ sudo vim /etc/pam.d/gdm-password
(...)
auth required pam_u2f.so authfile=/etc/Yubico/u2f_keys cue [cue_prompt=Remember to touch Key]
Bonus 2 - Securing Linux terminal TTY with YubiKey
If you want to secure access to Linux terminal for systems without GUI or when changing to terminal with for example Ctrl + Alt + F2 edit following file:
$ sudo vim /etc/pam.d/login
(...)
auth required pam_u2f.so authfile=/etc/Yubico/u2f_keys cue [cue_prompt=Remember to touch Key]
Bonus 3 - PAM configuration in separate file
You can have PAM configuration regarding YubiKey in separate file and include it in PAM configuration files. This example will be for YubiKey as sufficient authentication method.
$ sudo vim /etc/pam.d/u2f-sufficient
#%PAM-1.0
auth sufficient pam_u2f.so authfile=/etc/Yubico/u2f_keys cue [cue_prompt=Remember to touch Key]
After that include this file in all PAM configuration files like sudo, sudo-i, polkit-1. Because it's sufficient authentication method, put include line at the beginning of files.
sudo
$ sudo vim /etc/pam.d/sudo
#%PAM-1.0
auth include u2f-sufficient
(...)
sudo-i
$ sudo vim /etc/pam.d/sudo-i
#%PAM-1.0
auth include u2f-sufficient
(...)
polkit-1
$ sudo vim /usr/lib/pam.d/polkit-1
#%PAM-1.0
auth include u2f-sufficient
(...)