Assume the following scenario and please correct me if I am wrong somewhere:

There is a client and there is an SSH server that the client connects to. There is also a man-in-the-middle (MIM) which is able to intercept the client's incoming and outgoing traffic.

Now suppose that the client connects to the SSH server for the very first time and the server's public key info is not in the known_hosts file yet. The server sends its public key to the client, the client checks known_hosts file, does not find the server's public key there and hence the server now needs to prove its identity to the client. Identity is successfully proven (by using server's private key), but suppose that the client does not store the server's public key in the known_hosts after that (it is not mandatory to store it in the known_hosts, as far as I know).

The next time when client connects to the SSH server, the man-in-the-middle (MIM) intercepts client's connection request, and sends its own public key to the client, on behalf of the real SSH server. The client receives MIM's public key, inspects known_hosts file, and does not find the received public key in that file, so the "server" (MIM) needs to prove its identity again. Because the MIM's public key is associated with the corresponding private key, MIM successfully proves its identity to the client.

Is it possible to compromise security in that way? Correct me if I'm wrong somewhere please.

Someone told me that the server domain certificate is able to solve the problem, so additionally I would like to understand the purpose of host certificates. I have read that the certificate is put into known_hosts file just as the usual public key. But what's the point of using a certificate if we may use the same public key on all servers in domain, and simply put that public key into client's known_hosts file? Apparently, if there's no public key in known_hosts yet, the attack I've described above is still possible, and it doesn't matter whether the server uses certificate or not.

1 Answer 1


It looks like you assume that the identity of the server is proven by the server demonstrating that he owns the presented public key. But this does not prove the identity of the server from the perspective of the client.

An important part of validating the servers identity is that the client verifies the servers public key against the expected one. That's why the fingerprint is presented to the client for validation on first connect or if the key has been changed. This means that the fingerprint or public key needs to be known by the client up-front, i.e. before key validation. What you describe is instead blindly trusting any key presented to the user in the hope but not certainty that it is the correct one (TOFU - trust on first use).

Someone told me that the server domain certificate is able to solve the problem

Certificates in SSH have a similar role as certificates in TLS (and thus HTTPS). They have a public key inside and they are issued and signed by a certificate authority trusted by the client. In case of certificate based authentication the server presents the certificate which includes the public key and the issuers signature. The issuers signature can be used to validate that the certificate was issued by the locally trusted authority and thus that they public key in the certificate is really the expected servers key. After that the public key is used as in normal key based authentication, i.e. the server has to demonstrate that it owns the private key for the public key.

With certificates the client thus does not need to know every server key up-front. It is instead sufficient to trust a specific authority that it issues and signs the correct certificates which include the servers public keys. This makes it more scalable if you are dealing with lots of different systems which are all managed by a few entities.

For how to use certificates in SSH see for example How To Create an SSH CA to Validate Hosts and Clients with Ubuntu.

  • thanks for reply and thorough explanation. By "local authority" you probably mean the administration of server domain that the client intends to connect? i.e. the client receives the certificate from administration and writes it into his known_hosts file
    – mangusta
    Commented Jan 7, 2018 at 10:15
  • @mangusta: By local authority I mean the certificate authority which signed the server certificate (or usually multiple server certificates inside the same company) and which is configured as trusted by the client. And this is the one which is setup as cert-authority in the known_hosts file. Commented Jan 7, 2018 at 13:49
  • so you mean that the certificate cannot be signed by the server owners themselves? This link: ef.gy/hardening-ssh describes the way to sign a host certificate (by ssh-keygen -h), and from your words, this procedure cannot be done by server owners, it should be done by that certificate authority only? What if the sign will not belong to authority? Does the client verify that?
    – mangusta
    Commented Jan 7, 2018 at 14:19
  • 1
    @mangusta: sure the server owner might work as certificate authority too. But you have nothing won if every server owner signs its own certificate because then you would have to trust every server owner up-front - which is essentially the same as working without certificates where you would need to trust the servers key up-front. Certificates make sense if one party manages multiple servers and you trust this party instead of trusting each server. Commented Jan 7, 2018 at 14:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .