touch2sudo: Enable remote sudo two-factor authentication using Mac Touch ID

Binu Ramakrishnan
Jan 20 · 7 min read

The Touch ID on MacBook Pro and MacBook Air is an impressive feature that enables you to use your fingerprint for authentication. In this write-up, I’m going to show how we can extend this feature to authenticate remote SSH sudo commands.

sudo

As a good security practice, running sudo commands require some form of authentication. If you are using password based authentication scheme, you are often prompted for passwords before running sudo commands. Typing password all the time is cumbersome and a counterproductive activity for engineers. It also forces users to keep passwords on remote servers, which is not considered secure. Hence to avoid storing passwords in servers, we need to choose a different authentication scheme for sudo. One option is to completely disable sudo authentication. This is not recommended because as a user, you may accidentally do dangerous or irrevocable actions using your root privileges — imagine you unknowingly execute some scripts that contain sudo commands. Besides that, sudo authentication puts additional security barrier against local privilege escalation attacks in case of a server compromise.

Solution in a nutshell

There are a number of PAM based solutions available that support various authentication schemes for sudo. The solution we describe here use pam-ssh-agent-auth — a PAM module that does SSH key authentication for sudo. pam-ssh-agent-auth is based on SSH agent forwarding feature that allows the PAM module to authenticate sudo command using key cached in ssh-agent running on your workstation (Mac).

You can enable agent forwarding by adding sudo identities (keys) to your local ssh-agent, and then connect to remote host with ssh -A command-line flag (or by setting AgentForward flag in your ssh config file).

ssh-add is the command line tool to add identities (SSH private keys) to ssh-agent. An interesting optional feature provided by ssh-add for adding identities is -c option. It allows the user to force a confirmation program for the added identities before being used for authentication. For any authentication request for keys that require confirmation, ssh-agent attempts to execute SSH_ASKPASS confirmation program. The core of this writeup is a custom SSH_ASKPASS confirmation program — touch2sudo which authenticates your remote sudo commands using Mac Touch ID.

touch2sudo

touch2sudo is a standalone program, if executed authenticates the user either through Touch ID or password. A successful authentication (confirmation) is signaled by a zero exit status from touch2sudo program. To authenticate sudo commands, we configure touch2sudo as SSH_ASKPASS confirmation program, invoked by ssh-agent.

You can find the touch2sudo source code here:

The end to end setup is described in the following sections.

Mac configuration

Fingerprint authentication is done locally on Mac, but it acts as a gating mechanism for remote sudo authentication.

If you haven’t setup Touch ID, you can find the instructions from Apple here.

touch2sudo installation

You may either install touch2sudo binary using brew OR build it from source

Install using brew

Build from source

  1. Open touch2sudo.xcodeproj file using Xcode
  2. Build: (Product -> Build) If the build is successful, you would see this dialog:

3. Archive: (Product -> Archive -> Distribute Content -> Build Products -> Next -> Save) Save the archive folder. The touch2sudo executable binary will be in the <ArchiveDir>/Product/usr/local/bin path

4. Install: Copy touch2sudo binary to /usr/local/bin

Configure ssh-agent with touch2sudo

Generate a new SSH key pair for sudo:

Start ssh-agent

Now let’s configure the remote server.

Linux (Ubuntu) server configuration

Test Environment: Ubuntu 16.04

Follow the steps below to setup pam-ssh-agent-auth on your server:

Download pam_ssh_agent_auth

Build and install

PAM configuration

For demonstration purpose, I have created a user bob on remote host, and copied my SSH authentication keys to ~/.ssh/authorized_keys file:

On your Mac, generate new SSH key pair for sudo purpose. Copy the public key to server as follows:

SSH agent forwarding allows a remote host to forward authentication requests back to ssh-agent running on your workstation. This is commonly used in scenarios where users need to hop from one server to other. In such cases, without agent forwarding, the user needs to copy private keys to intermediate hosts — which is insecure (another option is to to SSH ProxyCommand).

To authenticate the sudo command, pam_ssh_agent_auth has to connect with the ssh-agent running on your Mac. The SSH_AUTH_SOCK environment variable on your remote host exports ssh-agent’s connect path (Unix domain socket file), and has to be made available for the PAM module.

Create a pam_sudo file, and add the following line. This will force bob to authenticate sudo commands.

The last step is to edit /etc/pam.d/sudo file to enable PAM authentication for sudo. Add the following line to the beginning of this file. Note that the order of the line is important.

Here is the file after the update:

Test touch2sudo

On your Mac:

Security considerations

It is well known that agent forwarding has an unintended security consequence. When you enable agent forwarding, it establishes a forwarding socket from the connected server (say host-A) back to ssh-agent running on your workstation. This means your ssh-agent is accessible from host-A, and can perform authentication when you initiate a new SSH session from host-A to host-B.

The problem with this model is, if your session to host-A is active, anyone with sufficient permissions (e.g. sudo users or an attacker who managed to compromised the host) on host-A can impersonate you and connect to host-B by performing authentication using keys from your ssh-agent.

Mitigation

The following steps can help mitigate agent forwarding for sudo:

  1. Do not use your SSH login keys for sudo authentication, instead use dedicated key for sudo authentication.
  2. On the server, the authorized_key file that contains the sudo authentication public key should be owned by root. On Linux (Ubuntu), copy sudo public key to /etc/ssh/sudo_authorized_keys/<user> file.
  3. On your workstation, use dedicated ssh-agent for sudo.

Example:

Following the above steps can stop an adversary impersonate your identity and move laterally to other servers. However certain SSH constraints in your environment may preclude you from following this method.

Useful links / References

http://evans.io/legacy/posts/ssh-agent-for-sudo-authentication/

https://github.com/mattrajca/sudo-touchid

https://jcs.org/notaweblog/2011/04/19/making_openssh_on_mac_os_x_more_secure

https://www.openssh.com/

Binu Ramakrishnan

Written by

Security Engineer

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade