news image

If you just want to know how to use the script, skip to the example usage section below.


The OpenSSH client uses a file called known_hosts to track the fingerprint for previously used ssh servers. This can help the SSH client detect when a man in the middle attack is taking place. If an attacker was to try this attack, the user’s client would show a serious warning and refuse to connect. This is done to stop the user from connecting to an attacker’s system. In my experience, Ubuntu and Debian servers seem to have the “HashKnownHosts” setting on by default. This setting does not seem to be the defacto default setting, so it may be disabled by the OS or vendor.

in 2005 a team from MIT wrote a paper about the potential threat of an SSH based worm. Their theoretical SSH worm would replicate by locating other SSH servers through the known_hosts file. To defend against this threat the OpenSSH team added a new option “HashKnownHosts” in version 4.0. This effectively feature hashes the IP and domains that are stored in the known_hosts file and effectively killed off the threat they had described. However, they did not foresee the GPU password cracking abilities that we have today.

Bruce Schneier also had a blog post about the issue and their paper.

Example known_hosts hashing configuration enabled in /etc/ssh/ssh_config:

The known_hosts file can help Red Teams

During an engagement I ran into a server and network that had detailed network monitoring. I had a shell and I had located a users SSH key. Normally you can read the .bash_history for a given user and see which hosts the user has used ssh to log into, but in this case it seemed the .bash_history file had rolled over. Since there weren’t very may ssh commands I decided to try to find a way to crack the hashes in the known_hosts file. Having a list of IP addresses with other SSH servers would be helpful to have, as I wouldn’t need to do a noisy network scan to locate them. Also, if an attacker only logs into servers that the admin has already used, there is a good chance this wont raise an alarm and you can stay undetected.

known_hosts file format

A non hashed known_hosts file example: ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA01yz1a/UkkdKsqNIfALi13OmJ305weWukUtdG5WY2xKBzc3UDqBTVndbpzMEeXl/A/4SAPdc/dUUVNYJWHc8SvcFa2n+NXduq6UPmimJYxX0glHLql9rhX9X6BrpYq93J08tcdPJlS88AF86oL0HRk1l3whN8x7v62UfPSF3/apihx5PQVEYI0rL47wi6gYPRb70CiEn1MCvIJLeyBaIjvhZ+LKsXhNafahGo36Ck7Tf2iqTNuuy56U/ijt0MHg3kOwEecVVbWS3RSASQCfu345BK2a4soeIG1JpfTakz23Cb5T76wBM63uUDvFmmjn+ljZlNafN/AQLwIfYyxQ/pw==

a hashed known_hosts example:

|1|wlPQdgFoYgYsqG6ae20lYopRLPI=|p61txQKmb+Hn49dsD+v0CNuEKd4= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAzhZmG33G/3FG3vm0eDdyX1u++i0ceakIkJNgDxVVy6MpodRrpwqXXQj8/OGT

This next example known_hosts file with a single IP address. These commands will explain a little bit more on how these hashes are created (these commands were taken from this post):

First, lets see what is in the known_hosts file:

$ cat ~/.ssh/known_hosts
|1|GOOqYoIUqAQ4Qsun3Lb9yhEY7bc=|wFUz1PicR/NNbqrgKz4NlClxDdI= ecdsa-sha2-nistp256 AAAAE2V---snip---

The first base64 encoded string is used as the salt:

$ echo -n "GOOqYoIUqAQ4Qsun3Lb9yhEY7bc=" | base64 -d | xxd -p

The second string, is the IP address of the server.

$ echo -n "" | openssl sha1 -mac HMAC -macopt hexkey:18e3aa628214a8043842cba7dcb6fdca1118edb7 | awk '{print $2}' | xxd -r -p | base64

My first approach at cracking the known_hosts hashes

I wanted to start off by clarifying that I am not the first to do this attack. I’ve seen at small handful of posts that describe the technique. This attack also only seems to work if the user logged into the SSH server with the IP address vs. using the domain name.

My first approach with this was to create a cracking dictionary with every possible internal IP address in it ex: The file was big, but not unmanageable. the private block is around 16 million IP addresses. However, the entire internet would be around 4.3 billion. My first approach worked fairly well, but I found a better way after doing some googling.

The optimized approach, mask attacks

I found the following post on the hashcat forums with information about using a mask attack for brute-forcing hashes for all IPv4 addresses. Hashcat mask attacks are used often as they can be better tuned for cracking vs. the brute force method. In our case it is easier to use a mask attack as you don’t need to generate a 4.3 billion IP address dictionary file. The IPv4 hcmask file included in this repository was originally downloaded from this pastebin post, but I’ve included it here to save you time.

Can OpenSSH find a solution to solve defend against this attack?

It doesn’t seem like there would be a clear solution. If they used a more expensive hashing algorythm like bcrypt, the GPUs could still crack the entire IPv4 address space for a single hash in ~50 hours with a single Nvidia 1080 GTX ti. A single card can do about 23223 bcrypt Hashes/second per this benchmark (4,294,967,296 ip addresses / 23223 hashes a second / 60 second per minute / 60 minutes per hour = 51.3 Hours). Also, if bcrypt was used, this could cause slowness or performance issues potentially, especially for lower powered embedded devices.

Example usage

#This is an example of what a hashed known_hosts file looks like:
cat ~/.ssh/known_hosts
|1|wlPQdgFoYgYsqG6ae20lYopRLPI=|p61txQKmb+Hn49dsD+v0CNuEKd4= ssh-rsa AAAAB3NzaC1yc2EAA--snip--==

#This will convert the hashed known_hosts file into a format that hashcat can attempt to crack:
python3 ~/.ssh/known_hosts

#To save the output from, lets redirect stdout to a file:
python3 ~/.ssh/known_hosts > converted_known_hosts

#Finally, to crack the "HMAC-SHA1 (key = $salt)" hashes, use the following hashcat command:
hashcat64.bin -m 160 --quiet --hex-salt converted_known_hosts -a 3 ipv4_hcmask.txt 

As you can see from the hashcat output above, the IP address was found to be Note: This cracking attempt was completed in about 1 minute on a single Nvidia 1080 GTX GPU.


Thanks to Jason and Eden for the suggestions on this post.

Read More

This site uses Akismet to reduce spam. Learn how your comment data is processed.