The Book of Gehn

Separate your SSH Agent Identities

March 15, 2019

Using a ssh-agent to handle our keys is handy.

When you need to access to different hosts jumping from one to another, forwarding the agent is much more secure than copying and pasting your keys around.

But if one host gets compromised it will expose your agent: even if the attacker will not get your secret keys he will be able to login into any system as you.

You cannot prevent this, but you can restrict this to reduce the splash damage.

Explicit is better than implicit

You can instruct to your ssh-agent to request your explicit permission to use a particular key.

This gives you the opportunity to detect when someone is trying to use your agent.

A simple alias is enough:

$ alias ssh-add='ssh-add -c'

To make it usable you are going to need a program that can ask you if a particular key can be used or not. There are several options but if you want simplicity I think that ssh-askpass is good enough.

Multiple ssh-agents

Even using an explicit confirmation, you agent may leak some info exposing all the public keys that it has.

This is because when you (or the attacker in your behalf) request a secure shell to a remote host, ssh will offer all the available public keys that the agent has.

Only if one is accepted, the agent will ask you confirmation; technically a public key is for that but it may reveal more than you want.

For example you could have ssh key for your personal github account and another key for your work.

You use the latter ssh key to log in to some work-related host and forward the agent.

But if you loaded both keys to the same agent, it may leak the fact that you have a personal github account.

The only way to prevent this is to not load all the keys in the same agent and use different ssh-agents instead.

Switch by hand

Assuming that you have two ssh-agents running, to use a particular one you need to set some environment variables in your current shell:

$ export SSH_AGENT_PID="$agent_pid"
$ export SSH_AUTH_SOCK="$sock_file"

Where $agent_pid and $sock_file are the process id of the agent and the socket file that it created for IPC.

But doing that by hand is error prone.

ssh-use-agent

For this I wrote ssh-use-agent, a simple script to spawn and switch between ssh-agents.

To install it, save the script somewhere and give it execution permissions.

For simplicity, create an alias to invoke it without remembering to source it.

$ alias ssh-use-agent=". ~/your-scripts/ssh-use-agent"

And to have a quick feedback about which ssh-agent is begin use, modify your prompt:

$ PS1='${SSH_AGENT_NAME:+(agent $SSH_AGENT_NAME) } \$ '

That works for Bash, depending of your shell and your personal configuration and taste those bits may vary.

To start using an agent run:

$ ssh-use-agent use personal

That will use an already running ssh-agent registered under the name personal and it will source into your terminal the required environment variables so any program spawned from there will use that agent.

$ echo $SSH_AGENT_PID
<pid>

$ echo $SSH_AUTH_SOCK
/tmp/<...>

$ echo $SSH_AGENT_NAME
personal

If no agent is registered under that name, ssh-use-agent will spawn a new ssh-agent for you.

It is up to you to load any ssh key to it later with ssh-add (or ssh-add -c).

Run ssh-use-agent disuse to dis-configure your terminal. Keep in mind that no agent will be shutdown.

$ ssh-use-agent disuse

$ echo $SSH_AGENT_PID
$ echo $SSH_AUTH_SOCK
$ echo $SSH_AGENT_NAME

To remove a key or all the keys use ssh-add as usual; to kill a particular ssh-agent use the traditional kill -15.

Related tags: bash, scripting, security

Separate your SSH Agent Identities - March 15, 2019 - Martin Di Paola