SSH is a very useful tool for anyone using Linux Environments. It’s a secure way to log into a machine remotely but can also do a lot more. With SSH one can create tunnels –  that is have the local machine listening on a specific port and pass whatever it receives through the tunnel and send it to a specified destination. SSH can also be instructed to automatically forward an X server session to the local X Server.

One inconvenience with SSH, like with so many other remote connecting tools, is that you have to provide a login and a password each time you want to log in to a target machine; but is this really necessary? It might surprise you that the answer is no, not really.

What are login and password used for? When we input a login and password we’re telling the remote machine ‘yeah I promise I really am the user that has permission to use you’. This is achieved by the remote machine assuming that only the authorised user knows the correct login and password.

Let’s think about this – the local machine already knows it’s us or else it wouldn’t have allowed us to log on right? So why can’t our machines just talk between themselves and vouch for us much like the Schengen area in Europe? Well, they can! We can do this using Public Key Authentication.

What’s Public Key Authentication?

In Public Key Authentication one has two keys: a private key and a public key. The private key as the name implies is a key which only our specific machine knows and has to be kept secret. The Public key is a key we distribute to other machines to prove that it is really us who are trying to connect to them.

How does this work?

The Public Key allows whoever has it to encrypt anything that only the machine that has the corresponding private key can decrypt.  So let’s assume we have two different machines called A and B. We want Machine B to allow access to Machine A, so Machine A needs to generate a private and public key and Machine B gets the public key. Now, whenever Machine A tries to connect to Machine B, B will tell A to prove that it really is Machine A. To do this Machine B will generate a large random number, encrypt it with the public key of Machine A and send it over to Machine A. If Machine A really is Machine A then it will have the private key that can decrypt the random secret number and send it back to Machine B.

At this point the target machine knows that the machine trying to connect to it is authenticated and the connecting machine already knows the correct user is logged on. There is no need to further identify anything else so access is granted. Convenient!

Granted that this is convenient but does this make me more secure or less secure?

There is no clear cut answer. In some situations this authentication method, when correctly implemented, can be considered more secure; however, there are certain situations where it can actually be a security risk.

How does this method make us more secure?

If we disable login and password-based authentication since we don’t need them, we get rid of the possibility of hackers brute forcing our credentials remotely. If they try to authenticate via SSH they will not be asked for credentials but for the secret number which they cannot tell as they do not have a corresponding secret key for that user/machine.

If there are scripts that require logging in to a remote machine using login and passwords, you’d need to have the credentials hardcoded in those scripts which is ugly and dangerous as you would need to physically protect the file. Simply editing that file becomes a risk for someone seeing it over your shoulder, whereas if you use certificates this is not required at all.

Passwords are a lot easier to guess than a 4096bit certificate. Passwords can be a simple six-letter word which is found in every dictionary out there; a 4096 bit certificate will not be in any dictionary and is virtually impossible to crack.

Finally you’re introducing one more element in the authentication system. With credential based authentication you’re effectively only authenticating yourself. With certificates you’re authenticating yourself and your machine.

How is it less secure?

The only issue where certificates are a security risk is if a machine is compromised. If an attacker gets access to one machine he can log on to every machine that the compromised machine has access to. This issue can be mitigated by password encrypting the private key itself; however, if we did this we’d lose the convenience of logging in without credentials as now each login would ask us for the password so the system can have access to the private key.

If your prime concern is security, then encrypted private key is the way to go. With such an implementation you’ll be a lot more secure than using the classic login and password based authentication.

Is this an acceptable risk?

In critical systems using unencrypted private keys to authenticate is not a good idea.  If a system is non-critical then most likely the risk is acceptable.  In a way once a machine is compromised the game is over in my opinion. Irrespective of what authentication mechanism one uses, if credential authentication is used and your machine is compromised then the attacker has a number of ways to get to the password. He can use key loggers, scan memory, Trojans, use modified version of tools to capture the password as well as sniff network traffic. A non encrypted certificate would only expedite the compromise to other systems by a little while in my opinion.

How can we mitigate this risk?

To fully mitigate the risk the only way is to encrypt the private key using a password; however, this will lose the ability to seamlessly log in without user interaction. If there are only some machines which you want to ensure are not compromised in the event of a breach then you can create two private keys and encrypt one of them. Copy the public key of the encrypted private keys to the servers that you want to be as secure as possible, and the public key of the unencrypted private keys onto the other machines where you want convenient logins (there is no limit as to how many private keys a machine can have).

How does one enable public key authentication on SSH?

First step is to switch to the user you want to give access to remote machines to. Then run ssh-keygen –t rsa. This will generate a 2048 rsa type key pair. If you want a larger key you can specify the bit size using the –b switch. So running ssh-keygen –t rsa –b 4096 will create a 4096 bit key.

In any case once you run the command ssh-keygen will ask where you want the key pair saved, by default it will choose .ssh directory under the user’s home directory and that’s exactly where we want it so just press enter. Finally it will ask what passphrase to use to encrypt the key. If you leave this empty it will be unencrypted and thus will not ask for a password to log in on any system where this public key will be deployed. If a password is entered then in the event that this machine is compromised the attacker will not be able to log in on any other machine before he gets access to the password which encrypts the private key.

Once we finish the above procedure two files will be created in the directory .ssh under our home directory – id_rsa and id_rsa.pub

id_rsa is the private key and needs to be protected as best as possible. Anyone who gets access to this file can log in without a password if the private key was not encrypted.

id_rsa.pub is the public key and this is the key we need to distribute to all machines we want this user to log into. To do that, append the contents of this file to the file authorized_keys  on the remote machine. This file should reside in the user you want to map to home directory/.ssh/ ie ~/.ssh/ if it doesn’t exist just create it. If it does exist append the content of id_rsa.pub to a new line. This can either be done manually or using the handy utility ssh-copy-id. Simply run ssh-copy-id –I ~/.ssh/id_rsa.pub user@machine

This will automatically copy the required public key. Now you can log in from the original machine to this machine without a password. If you want the reverse just repeat the process on the other machine.

Important things to consider:

  • Ensure you do not do this on the root account. In the event of compromise it will limit damage.
  • Disable credential based login if you don’t need them anymore.
  • Some software, both on Linux as well as Windows, that communicates with Linux machines through the use of SSH such as GFI LANguard Network Security Scanner may also support public key based authentication.  To configure such software to make use of this authentication mechanism the same steps are involved.
  • Generate a private and public key using ssh-keygen utility but now provide the private key to the software you want to give access to and deploy the public key on the machines you want that software to access. Obviously it is paramount to ensure the safety of the private key here as well; anyone who gets access to that file gains access to all the machines that have the corresponding public key.
  • If a private key gets compromised simply delete the corresponding public key from the file ~/.ssh/authorized_keys and that private key will no longer be able to log in. It is very important to ensure no new public keys were added in the event of compromise. Ideally to be 100% safe, all the authorized_keys should be wiped out and new keys should be generated. This will avoid the possibility that whoever compromised a private key didn’t copy other private keys and is now using them.