How can I add a host key to the SSH known_hosts
file securely?
I'm setting up a development machine, and I want to (e.g.) prevent git
from prompting when I clone a repository from github.com
using SSH.
I know that I can use StrictHostKeyChecking=no
(e.g. this answer), but that's not secure.
So far, I've found...
GitHub publishes their SSH key fingerprints at GitHub's SSH key fingerprints
I can use
ssh-keyscan
to get the host key forgithub.com
.
How do I combine these facts? Given a prepopulated list of fingerprints, how do I verify that the output of ssh-keyscan
can be added to the known_hosts
file?
I guess I'm asking the following:
How do I get the fingerprint for a key returned by ssh-keyscan
?
Let's assume that I've already been MITM-ed for SSH, but that I can trust the GitHub HTTPS page (because it has a valid certificate chain).
That means that I've got some (suspect) SSH host keys (from ssh-keyscan
) and some (trusted) key fingerprints. How do I verify one against the other?
Related: how do I hash the host portion of the output from ssh-keyscan
? Or can I mix hashed/unhashed hosts in known_hosts
?
The most important part of "securely" adding a key to the
known_hosts
file is to get the key fingerprint from the server administrator. The key fingerprint should look something like this:In the case of GitHub, normally we can't talk directly to an administrator. However, they put the key on their web pages so we can recover the information from there.
Manual key installation
1) Take a copy of the key from the server and get its fingerprint. N.B.: Do this before checking the fingerprint.
2) Get a copy of the key fingerprint from the server administrator - in this case navigate to the page with the information on github.com
3) Compare the keys from the two sources
By placing them directly one above the other in a text editor, it is easy to see if something has changed
(Note that the second key has been manipulated, but it looks quite similar to the original - if something like this happens you are under serious attack and should contact a trusted security expert.)
If the keys are different abort the procedure and get in touch with a security expert
4) If the keys compare correctly then you should install the key you already downloaded
Or to install for all users on a system (as root):
Automated key installation
If you need to add a key during a build process then you should follow steps 1-3 of the manual process above.
Having done that, examine the contents of your
github-key-temp
file and make a script to add those contents to your known hosts file.You should now get rid of any
ssh
commands which haveStrictHostKeyChecking
disabled.You can mix hashed/unhashed entries in your known_hosts file.
So if you want to add github key, you can just do :
ssh-keyscan github.com >> ~/.ssh/known_hosts
If you want it hashed, add -H
ssh-keyscan -H github.com >> ~/.ssh/known_hosts
Note: this is vulnerable to MITM attack, it answers to the "Related" part of the question only.
The easiest way is to manually fetch the keys using
ssh-keyscan
, verify them manually:And add them to your script, which will then carry the "authoritative" public key.
I wrote simple script (add_to_known_hosts) to handle this:
It won't create duplicate entries in the known_hosts file, and it will check if the fingerprint matches one provided as second argument.
Now that GitHub provides their SSH keys and fingerprints via their metadata API endpoint (as of January 2022), you can leverage the trust you have in GitHub's TLS certificate used on
api.github.com
(due to it being signed by a certificate authority (CA) which is in your system's trusted root certificate store) to securely fetch their SSH host keys.If you have
jq
installed you can do it with this one-linerOr if you want to use Python
Automating SSH Known_Hosts fingerprint check
I have been trying to do this in Python on Jupyterhub for a little while but @Michael's answer was really helpful!
Let us be clear -- by design this step to confirm a known host should NOT be automated given susceptibility to man in the middle attacks (more info here, but it should be obvious why this is a concern).
Manually checking SSH RSA Fingerprint for GitHub.com with Python & Bash
The insecure workaround
-o "StrictHostKeyChecking no"
was alright for testing but glad to have an alternative.!
bang in Jupyter to invoke bash command forssh-keyscan
&cat
Assert Fingerprints match to confirm known hosts
You can now use a python assertion to ensure authenticity of our trusted RSA fingerprint vs the Scanned-over-your-internet RSA fingerprint:
Thanks and a much better workaround to ignoring the strict check!
If you would like to check if the key exists before generating a new one:
In addition, in my case I had to mention a specific port:
To generate the known_hosts file, after generating your private and public keys and copied the public key to site.com, you can do