SSH: Bring Your Keys With You

Introduction

This might be useful for someone else also. There are some (not too frequent) situations when you need to switch to another user, but keep the ssh-agent in the process. For example, I sometimes use this to switch to another user that has a git repo and files with some particular permissions, but I need to git pull or git push to a repo with my own credentials.

  • This might pose a security risk in your environment, so think it through before you do this

For this tutorial, you need the acl package (if you run Ubuntu).

$ sudo apt install acl

To bring your keys to another user:

setfacl -m ops:x $(dirname $SSH_AUTH_SOCK); setfacl -m ops:rwx $SSH_AUTH_SOCK; sudo --preserve-env=SSH_AUTH_SOCK -iu thatOtherUser

Do your thing as that user then exit and remove the ACLs:

setfacl -b $(dirname $SSH_AUTH_SOCK) $SSH_AUTH_SOCK;

Theory

Necessary components in this hack:

  • You forward the authentication agent to the remote host
  • You set the permissions of the authentication socket
  • You start a new shell as a different user, using sudo

To bring your ssh-agent with you when you ssh to another host, you need to start ssh with the -A option to begin with.

ssh -A myUser@remote-host

From the man page:

     -A      Enables forwarding of the authentication agent connection.  This can
             also be specified on a per-host basis in a configuration file.

             Agent forwarding should be enabled with caution.  Users with the abi-
             lity to bypass file permissions on the remote host (for the agent's
             UNIX-domain socket) can access the local agent through the forwarded
             connection.  An attacker cannot obtain key material from the agent,
             however they can perform operations on the keys that enable them to
             authenticate using the identities loaded into the agent.

ssh will set up you environment properly, with the environment variable SSH_AUTH_SOCK properly set.

admin.mlue@com-adm-l01:~$ ssh-add -L
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGGXBzN/uaFrfDLRZa2TUUfMaiXdaEiNcnCMl6jqj1mzSRIUc5zTo7qvmLSQBrlpxt9b+SfR3akDiQ3ZJFI03Dl4F7PUqMWBKH/2mRy+m6iMiY/yKrd/HvFebxDtt4Xl+KoEMoiCC5ShPZN6XFxATIsILWoPjQYtBwU1FO4joprpVUTz0qE/nakpw59g7v3eFfC5s2UgUlxw7qvxjNhR+bXWI2unBmyHQSjncKsZ9JviMbN6XG5sBAQHRBX1rl6J7jyczJGE6oJXLwwUhqe8iPW9nQWACC5pXcFO9uOAgJIYf7WbLSfZxbS3YIy8Q18+l7c1YtP/eKR1f+1l7djnp9 cardno:000607543890

The ssh agent needs to read and write to a socket, which is created when you start the ssh-agent. This socket is owned by you, and cannot be read/written by another user. You need permission to both the directory in which the socket is created, and the socket itself.

admin.mlue@com-adm-l01:~$ env | grep SSH_AUTH_SOCK
SSH_AUTH_SOCK=/tmp/ssh-xz6frza4tC/agent.40313
admin.mlue@com-adm-l01:~$ ls -la $(dirname $SSH_AUTH_SOCK)
total 16
drwx------  2 admin.mlue 3172  4096 Apr 29 12:58 .
drwxrwxrwt 21 root       root 12288 Apr 29 12:58 ..
srwxr-xr-x  1 admin.mlue 3172     0 Apr 29 12:58 agent.40313

The way that I use if I need to give another user access to this socket, is to use the setfacl. I don’t normally like acl’s, as it is tricky to remember what permissions you gave which file. But this is actually a use case where it is useful.

The effect of the setfacl disappears as soon as you log out of the session (as the socket is deleted).

When you switch to the other user, you will need to bring the socket file with you in the SSH_AUTH_SOCK environment variable. Most sudo configurations will reset the environment when starting the shell for the other user (which is good). The best way I know of, to bring the environment variable with you, is to tell sudo that you want to keep that variable.

sudo --preserve-env=SOME_VARIABLE -iu OTHER_USER

Bringing your ssh agent with you to a remote system is always a bit risky. Any other root user can hijack your SSH_AUTH_SOCK socket and user your credentials. One way to protect yourself is to:

  • Store your ssh key on a Yubikey
  • Configure the Yubikey to only authenticate after you touch it

That way, your credentials will only be used after you physically touch the Yubikey. This is out of scope for this article, though.

This is the End

To simplify my life, I created an alias and a function to simplify my life. The alias ops to just switch to that user, and the function ops-with-agent to switch to the user and bring my ssh-agent with me.

$ alias | grep ops
alias ops='sudo -iu ops'
function ops-with-agent(){ setfacl -m ops:x $(dirname $SSH_AUTH_SOCK); setfacl -m ops:rwx $SSH_AUTH_SOCK; sudo --preserve-env=SSH_AUTH_SOCK -iu ops "$@"; setfacl -b $(dirname $SSH_AUTH_SOCK) $SSH_AUTH_SOCK; }

Note: After you exit the session for the other user, it will still have the permissions. You remove all ACL settings on the socket and the socket directory with setfacl -b:

setfacl -b $(dirname $SSH_AUTH_SOCK) $SSH_AUTH_SOCK