Breaking Down A Python Reverse Shell One-Liner
Hello, World! In this article, we will dissect the most popular Python reverse shell one-liner that is used in ethical hacking to obtain remote command execution on a target machine. We will go through the one-liner, line-by-line, to understand how we can use built-in Python modules and how we manipulate Linux file descriptors to achieve remote access to a machine. Let’s do it!
This is the one-liner we will discuss:
And this is the prettified version of the one-liner above that will we refer to throughout this article:
The Reverse Shell
Establishing a Connection
The very first objective of this Python one-liner is to establish a remote connection to the target machine using Python’s built-in
socket module. If you want to know more about sockets, check out this article I wrote regarding creating a persistent Python backdoor in which I describe sockets in more detail. In short, line 5 in the snippet above is create an IPv4, TCP-based socket. The line that follows specifies the IP address and port to connect to which would be the attacker’s IP address and listening port.
Overwriting File Descriptors
os module allows us to interact with the underlying operating system. This reverse shell is only using one function from this library called
dub2 . This function will duplicate the file descriptor provided as the first argument, which in this case is the file descriptor of the socket. The second argument to the
dup2 function will be the value of the new file descriptor that will be created. The
dup2 function is invoked three times in this Python reverse shell and the new file descriptors being created have the values of 0, 1, 2. Why these values?
When using the CLI, there are 3 data streams that are used to handle different types of data streams:
- stdin — input data stream (this could be data from your keyboard or data piped from one command to another)
- stdout — this is the output from a program that gets written to the console
- stderr — error messages generated by a program and printed to the console
So by duplicating the socket’s file descriptor into the file descriptors 0, 1, and 2 for the current process, we are redirecting the stdin, stdout, and stderr data streams into the socket connection that was established with the attacker’s machine. The image below shows that the file descriptors 0, 1, and 2 for the process created on the target machine when executing the reverse shell are all redirected into the created socket:
Here’s what the file descriptors look like when you don’t duplicate the socket’s file descriptor (lines 7, 8, and 9) and overwrite the existing stdin, stdout, and stderr file descriptors:
As you can see, the stdin, stdout, and stderr file descriptors still point to their normal pty or pseudo-terminal, in this case
/dev/pts/0 . This means that the shell that is spawned by our reverse shell will not be able to handle any of our command requests or send us back command output because this shell will run as if it were a normal shell on the target machine where stdin, stdout, and stderr are handled locally.
Spawning a Shell
To spawn a shell, this reverse shell is using python’s
subprocess module which allows for the creation of “subprocesses”. From this module, the reverse shell is invoking the
call function which is used to start a program as a subprocess. Because we are trying to get remote command execution with this Python code we need to run a shell program such as Bash that will allow us to execute system commands. The
call function allows us to pass a program name to run, followed by any arguments for that program. Line 10 shows that we provide only one argument to the Bash shell which is the
This makes the spawned shell an interactive one, meaning that the data to this shell will be read from and written to a terminal as opposed to taken in as program arguments.
Running the reverse shell should result in a connection back to the attacker machine and should enable the attacker to execute commands remotely on the target machine.
And there you have it! You can now continue to pop your Python reverse shells but also have a basic understanding of how they operate under the hood. If you enjoyed reading this article, please follow me on Medium for more cybersecurity-related articles and on GitHub for more cybersecurity-related programming projects.
binexisHATT - Overview
My name is ✨ Alexis Rodriguez ✨ and I am a Cybersecurity Analyst focused on Red teaming.