Safer SSH agent forwarding
Vincent Bernat
ssh-agent
is a program to hold in memory the private keys used by
SSH for public-key authentication. When the agent is running, ssh
forwards to it the signature requests from the server. The agent
performs the private key operations and returns the results to ssh
.
It is useful if you keep your private keys encrypted on disk and you
don’t want to type the password at each connection. Keeping the agent
secure is critical: someone able to communicate with the agent can
authenticate on your behalf on remote servers.
ssh
also provides the ability to forward the agent to a remote
server. From this remote server, you can authenticate to another
server using your local agent, without copying your private key on the
intermediate server. As stated in the manual page, this is
dangerous!
Agent forwarding should be enabled with caution. Users with the ability 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. A safer alternative may be to use a jump host (see
-J
).
Update (2022-10)
See for example Matrix’ 2019 post-mortem about their security incident involving unsafe SSH agent forwarding.
As mentioned, a better alternative is to use the jump host feature: the SSH connection to the target host is tunneled through the SSH connection to the jump host. See the manual page and this blog post for more details.
If you really need to use SSH agent forwarding, you can secure it a bit through a dedicated agent with two main attributes:
- it holds only the private key to connect to the target host; and
- it asks confirmation for each requested signature.
The following alias around the ssh
command will spawn such an
ephemeral agent:
alias assh="ssh-agent ssh -o AddKeysToAgent=confirm -o ForwardAgent=yes"
With the -o AddKeysToAgent=confirm
directive, ssh
adds the
unencrypted private key to the agent but each use must be
confirmed.1 Once connected, you get a password prompt for
each signature request:2
But, again, avoid using agent forwarding! ☠️
Update (2020-04)
In a previous version of this article, the
wrapper around the ssh
command was a more complex function.
Alexandre Oliva was kind enough to point me to the simpler
solution above.
Update (2020-04)
Guardian Agent is an even safer alternative: it shows and ensures the usage (target and command) of the requested signature. There is also a wide range of alternative solutions to this problem. See for example SSH-Ident, Wikimedia solution and solo-agent.
Update (2022-01)
OpenSSH 8.9 will be able to restrict usage of forwarded SSH agent keys. However, the protection offered by these restrictions is quite limited. You should continue to avoid using agent forwarding.