Sunday 26 July 2015

SSH Fingerprint from a PCAP

This post will cover how to generate a SSH public key fingerprint from captured network traffic. There’s also a Python script that you can download (ssh_fingerprint_extractor.py) that will go over a binary file searching for the public key that a typical SSH server presents and generate the fingerprint of it.

What is a SSH Fingerprint?

You know when you try to connect for the first time to a SSH server with a client like Putty, it will present to you a fingerprint that looks something like this “43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8” and then it’ll ask if you’d like to accept it. Most people instruct their SSH client to remember the key, so that they’re not warned the next time they try to connect to the server. The idea is to prevent a Man-in-the-Middle (MITM) attack by verifying that the server’s public key is what we expect to get.


The Scenario

I’ve recently worked on an incident response (IR) case where the attacker was tunnelling their connections using the malware they implanted on some of the end nodes. When investigating a PCAP with tunnelled connections, I came across a SSH session. The natural thing would be to determine what host the attackers were accessing. However, based on the PCAP we couldn’t tell what the end-point system was.
Wireshark verified my suspicions that the SSH server needs to send its public key to the client before the encrypted communication can start. If we could produce the SSH fingerprint from the captured data then we can compare it to the once presented by the servers on the network and therefore pin point what systems the attackers were accessing.




The Solution

Googling to see if someone has had a similar problem yielded Didier Steven’s blog post about calculating a SSH fingerprint from a (Cisco) public key. Studying his code quickly revealed that the “mysterious” fingerprint is nothing else but MD5 of the public key, presented in a rather peculiar form, perhaps the byte separation was meant to help folks swiftly perform a visual inspection if it matches what they should expect to see.
Looking at the PCAP in Wireshark I quickly realised that the public key has a recognisable keyword “ssh-rsa”, which is preceded by a byte sequence “\x00\x00\x00\x07” and the key size before that. So all the code needs to do is look for the keyword, read the size, grab the data and calculate MD5 of it.
While testing the tool, I was surprised to learn that in fact there were two SSH public keys, referred to by Wireshark as KEX DH host key and KEX DH H signature; you’re only interested in the host key as this is what the SSH client will take as the fingerprint.

SSH Servers Scanning

Say you extracted the SSH fingerprint from the PCAP and you need to find the server it belongs to – nothing easier! As it turns out, nmap has a NSE script called ssh-hostkey that will do that for you. Example usage:

nmap [IP_range] --script ssh-hostkey --script-args ssh_hostkey=full -oX output.xml

All that's left now is to grep the XML file or write a parser. Have fun!