Re-use of SSH keys across thousands of devices

John Matherly, of Shodan fame, posted a blog to /r/netsec (comments are relatively interesting) last week showing how he had used the Shodan Python API combined with “facets” to find the most common SSH fingerprints.

I’m a heavy user of Shodan, but largely via the web front-end. I thought I’d take this as an opportunity to get the API working. It’s very easy. All instructions are under Ubuntu 14.04, but will likely work for any Ubuntu like distro.

First make sure you have easy_install which is part of setuptools – you will likely have this already if you have built anything big in Python:

sudo apt-get install python-setuptools

Next, install the Shodan API itself:

easy_install shodan

Simple – we should be done now.

You need to sign up to Shodan and get an API key. If you use Shodan regularly, I would suggest getting a paid-for plan (it’s very good value), but a free account will have access to the API, albeit with limitations.

Let’s test it with a simple search first:

import shodan

SHODAN_API_KEY = "dontbeusingmykey"

api = shodan.Shodan(SHODAN_API_KEY)

    results ='port:22 country:GB')

    print 'Results found: %s' % results['total']
    for result in results['matches']:
        print 'IP: %s' % result['ip_str']
        print result['data']
        print ''
except shodan.APIError, e:
    print 'Error: %s' % e

This should throw a huge list of results back for any hosts in the UK (country code GB which I always forget) with port 22 open:

Key type: ssh-rsa
Fingerprint: 4c:39:7e:bc:38:b3:22:53:4a:a0:81:29:04:9c:03:35

Key type: ssh-rsa
Fingerprint: 7d:3b:18:9d:00:54:2f:44:4e:5a:cc:07:b9:2c:1e:d3

Now this is interesting and useful, but Shodan has a very neat bit of functionality called “facets”. The simplest way of explaining these is that it allows me to group the results and show you the top by count.

For example, we could find the top ports open across the UK:

import shodan

SHODAN_API_KEY = "jesustakethewheel"

api = shodan.Shodan(SHODAN_API_KEY)


    results = api.count('country:GB', facets=[('port', 10)])

    for facet in results['facets']['port']:
        print '%s -- %s' % (facet['value'], facet['count'])

except shodan.APIError, e:
    print 'Error: %s' % e

Which gives us the following results:

7547 -- 2519825
80 -- 1816315
443 -- 1051424
22 -- 506137
5060 -- 499811
1723 -- 423132
25 -- 382716
8080 -- 351585
500 -- 242772
21 -- 241357

As expected, we have the common ports of 80 (http), 443 (https), 22 (ssh), 25 (SMTP), 8080 (http or http proxy), and 21 (telnet). What’s the top port 7547 though?

This is TR-069 or CWMP (CPE WAN management protocol), a http based protocol that allows the remote management of customer premises equipment i.e. lets your ISP remotely control your router. It’s open on a worryingly large number of routers and suffers from a number of vulnerabilities, most notably the “Misfortune Cookie“.

Anyway, facets also let us group by more esoteric fields, such as the SSH fingerprint presented each time you try to connect via SSH. This is the focus of John’s blog post.

import shodan

SHODAN_API_KEY = "hesapiratehesaftermybooty"

api = shodan.Shodan(SHODAN_API_KEY)


    results = api.count('port:22 country:GB', facets=[('ssh.fingerprint', 10)])

    for facet in results['facets']['ssh.fingerprint']:
        print '%s -- %s' % (facet['value'], facet['count'])

except shodan.APIError, e:
    print 'Error: %s' % e

I’ve restricted this to the UK – I know the lay of the land better, and dealing with any issues found is a little easier both from a communication and legal standpoint.

The results are as follows:

7c:a8:25:21:13:a2:eb:00:a6:c1:76:ca:6b:48:6e:bf -- 11758
a8:99:c2:92:08:fb:5e:de:4b:96:14:de:61:df:ad:6d -- 7990
03:56:e6:52:ee:d2:da:f0:73:b5:df:3d:09:08:54:b7 -- 2239
b4:af:64:0c:9a:ed:ed:4d:b1:c0:12:5d:c9:e4:c8:f0 -- 1217
eb:65:52:6e:40:28:af:a6:36:5b:b3:b4:0c:5d:32:3d -- 1091
39:aa:e4:e9:a2:e7:c1:04:9d:00:9f:b6:99:d5:9c:bd -- 880
57:94:42:63:a1:91:0b:58:a6:33:cb:db:fe:b5:83:38 -- 782
34:47:0f:e9:1a:c2:eb:56:eb:cc:58:59:3a:02:80:b6 -- 630
14:96:82:72:6f:bc:a5:14:53:1c:72:71:0d:8b:cb:c2 -- 598
f9:76:13:e7:86:11:8b:64:0f:e0:39:ea:e9:14:a7:18 -- 471

Those top three are very, very common! How has this happened?

Let’s plug the top one back into Shodan via the web front-end:

Shodan results

What can we tell from those organisations and hostnames? These are all devices on consumer broadband connections. Routers, NAS, other devices with SSH open.

So what is the issue here? Why are these duplicate SSH fingerprints an issue?

The SSH fingerprint is a hash of the public key used by the router for SSH communication. It provides a human-readable way of checking that you are connecting to the host you are expecting to connect to. If it has a different public key, you should nearly always get a different fingerprint.

SSH keys should be unique per device. The first time they boot, they should use a source of entropy to generate unique keys. The reason so many devices have the same keys is that the keys are stored in firmware and are not changed.

Having the same fingerprint means it is no longer possible for you to authenticate the device you are connecting to. Is it your router, or another person with the same router? Who knows!

It also, worryingly, means that there is a private key that could be used to impersonate and possibly even access these devices. This key may be stored in the firmware of these devices and recovered. This has happened in the real-world.

It is worthwhile noting, that even with the public/private keypair, you still need to MITM a SSH conversation to be able to decrypt it. SSH uses Diffie-Hellmann key exchange to ensure Perfect Forward Secrecy. The session keys are forgotten and the conversation can never be decrypted.

But above all, the biggest question is why is SSH open on so many broadband connections? Routers shouldn’t have SSH open like this. If they are NAS or similar behind the router and using UPnP to forward ports, why are routers still allowing this? If SSH is open by default, it would suggest that there is at least one account that can login by default. If the SSH keys are the same across all devices, how are we to know that the login credentials differ from device to device?

Leave a Reply

Your email will not be published. Name and Email fields are required.

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