🛡️ Methodology Checklist

  • Check if TTY available: tty — if not, upgrade
  • Python PTY: python3 -c "import pty; pty.spawn('/bin/bash')"
  • Background shell: Ctrl+Z
  • Terminal raw mode: stty raw -echo; fg
  • Fix terminal size: stty rows [R] columns [C]
  • Export TERM: export TERM=xterm
  • Use script /dev/null -c bash alternative if Python unavailable

🎯 Operational Context

Use when: Basic reverse shell obtained and need PTY for interactive commands (sudo, su, vi, mysql, ssh). Think Dumber First: python3 -c 'import pty; pty.spawn("/bin/bash")' — run immediately on any non-interactive shell. Then background with Ctrl+Z, run stty raw -echo; fg, then export TERM=xterm. This takes 30 seconds and unlocks sudo, arrow keys, and tab completion. Skip when: Already have SSH or Meterpreter session — these provide full PTY natively.


⚡ Tactical Cheatsheet

CommandTactical Outcome
/bin/sh -iSpawn interactive shell using sh flag
/bin/bash -iSpawn interactive bash shell
python3 -c 'import pty; pty.spawn("/bin/bash")'Python 3 PTY spawn (most common)
python -c 'import pty; pty.spawn("/bin/sh")'Python 2 PTY spawn
script /dev/null -c bashAlternative PTY spawn without Python
perl -e 'exec "/bin/sh";'Perl shell spawn
ruby -e 'exec "/bin/sh"'Ruby shell spawn
lua: os.execute('/bin/sh')Lua shell spawn
awk 'BEGIN {system("/bin/sh")}'AWK shell spawn (fallback — nearly always available)
find . -exec /bin/sh \; -quitFind command breakout
find / -name nameoffile -exec /bin/awk 'BEGIN {system("/bin/sh")}' \;Find + AWK breakout
vim -c ':!/bin/sh'Vim breakout (one-liner)
sudo -lCheck sudo rights (run after getting interactive shell)
ls -la [path]Check file permissions post-spawn

🔬 Deep Dive & Workflow

Why You Need an Interactive Shell

When gaining initial access through a web exploit or dumb reverse shell, you land in a non-TTY (non-interactive) environment:

  • No command prompt
  • sudo, su, passwd fail silently
  • Interactive text editors (nano, vim) don’t work
  • Ctrl+C kills your connection instead of the current command
  • Tab completion and history don’t work

The goal is to upgrade to a fully interactive TTY before doing post-exploitation.

Method Priority (Check What’s Available First)

which python python3 perl ruby lua awk
MethodPriorityNotes
Python3/PythonFirstMost commonly installed
script /dev/null -c bashSecondWorks when Python is absent
PerlThirdCommon on older systems
AWKFourthNearly always present on Unix
RubyFifthPresent on dev/web systems
find breakoutSixthGTFOBins fallback
/bin/sh -iAlways trySimplest; may already work

Vim Breakout (Two Methods)

# Method 1: Command line (never opened vim yet)
vim -c ':!/bin/sh'
 
# Method 2: Already inside vim
:set shell=/bin/sh
:shell

Particularly useful when vim has SUID or is allowed via sudo -l.

find Command Breakout

# Direct shell execution (most reliable)
find . -exec /bin/sh \; -quit
 
# Via AWK (if exec is restricted)
find / -name [EXISTING_FILE] -exec /bin/awk 'BEGIN {system("/bin/sh")}' \;

If find can’t locate the named file, the shell won’t spawn. Use . (current dir) or an existing file.

After Spawning — Immediate Checks

# 1. Check sudo rights (critical for privilege escalation)
sudo -l
 
# 2. Check file permissions
ls -la /path/to/file
 
# 3. Check current user
whoami && id
 
# 4. Then stabilize (see Shell_Stabilization)

sudo -l often fails in an unstable/non-TTY shell — stabilize first if it returns nothing useful.

GTFOBins Reference

For restricted environments (service accounts, limited shells), check GTFOBins for the specific binary available: gtfobins.github.io Filter by: shell, sudo, file read, file write


🛠️ Troubleshooting & Edge Cases

ProblemCauseFix
python3 not foundMinimal OSTry: python -c 'import pty; pty.spawn("/bin/bash")', script /dev/null -c bash, socat exec:'bash -li',pty,stderr,setsid,sigint,sane
After stty raw -echo and fg, nothing visibleTerminal state issueType reset blindly and press Enter; or type export TERM=xterm and Enter
Arrow keys still not workingstty not applied correctlySet manually: stty rows 38 columns 116; adjust to your terminal size
pty.spawn fails silently/bin/bash not availableTry: pty.spawn('/bin/sh') or pty.spawn('/bin/dash')
Ctrl+C kills shell after stty rawRaw mode passes Ctrl+C to shellUse Ctrl+C carefully; Ctrl+Z to background, fg to restore

📝 Reporting Trigger

Finding Title: Fully Interactive Shell Obtained Post-Exploitation Impact: Upgrading a basic reverse shell to a fully interactive PTY enables running interactive commands (su, sudo, ssh, database CLI tools) that require a terminal, significantly expanding post-exploitation capability from the initial shell access. Root Cause: N/A — operational capability documentation. Recommendation: Implement network egress controls to prevent reverse shell establishment. Deploy EDR to detect PTY spawn commands from web process parents. Alert on python pty.spawn and socat exec usage from web application process context.