OpenSSH stores lists of SSH public keys in known_hosts
files, so it can verify that the host you're logging into is the host
you expect and not a man-in-the-middle attacker. To reduce the risk
of island-hopping attacks, OpenSSH has a HashKnownHosts yes
option to store HMAC-SHA1 encrypted versions of host names and
IPs in your known_hosts
files rather than the clear text. This
makes it harder for an attacker to use the information stored in your
known_hosts
. However, it also makes it harder for you to use that
information.
I was digging through my known_hosts
file yesterday compiling a list
of servers where I have login accounts. I keep better track of these
things recently (using GPG to symmetrically encrypt the list),
but my known_hosts
file predates my quality-accounting phase.
Anyhow, I wrote up some simple tools to make reverse-engineering a
known_hosts
file a bit less painful.
You can use your monkeysphere keyring to see if you recognize any of the public keys. This avoids having to deal with the hashed names at all, but assumes none of your servers are sharing keys. unhash-known-hosts.sh automates this:
$ unhash-known-hosts.sh path/to/known_hosts
GnuPG ID 01234567 (ssh://server.example.net) matches |1|Bvjsg3lqJJ/M9rTYz1HfY+T/RoM=|DhZlGg3GFMWtVcjz4LNfJ8afi7w=
did not match |1|vug6FlX6GCaIIzkv3wS3zftQyyw=|PdMYEIaWTzHCv/4ZhNiR2DD6E0A=
...
Once you've got the low-hanging fruit out of the way, you can get a list of the high-hanging fruit:
$ unhash-known-hosts.sh path/to/known_hosts | sed -n 's/^did not match //p' > unknown_hosts
Start guessing with crack known hosts.py! IPs are usually a
good starting point, because any host in your known_hosts
file must
have an entry for its IP.
$ crack_known_hosts.py --known-hosts unknown_hosts --ip 192.168.*.*
You can also run a full scan of alphanumeric entries up to a specified length (this gets slow quickly, which is, after all, why you hashed the entries in the fiest place).
$ crack_known_hosts.py --known-hosts unknown_hosts --alphanum 16
Removing entries from unknown_hosts
as you crack them will make
future crack_known_hosts.py
attempts on that file faster.
Once you've cracked one name, you can use unique known hosts.py to find other entries that share the same key.
$ unique_known_hosts.py path/to/known_hosts
And there you have it. Happy cracking! ;).