As everything today run on the web we (pentesters, ethical hackers, etc) often get our first foothold in the target network through a webshell. This is often a primitive non-interactive shell over HTTP leaving us with bad options for traversing the system in a interactive way. We will here only briefly discuss why a non-interactive shell is bad, as it’s not relevant for this post, but if you want you can read more about the pains of non-interactive-shells
The problem: The HTTP Protocol is typically “request/reply”, so sitting in a shell wanting to change a directory can be really frustrating.
Often you find yourself running commands the following way on a webshell:
This is not an unsolvable problem at all but often you need a proper shell with
TTY for this and tools like
vim and a simple
We also want to setup some network tunnels to the internal network but this is also out of reach. Therefore our goto is often to look for misconfigured firewalls so we can use a normal TCP connection.
During a pentest the difference between a properly configured firewall and one with misconfigurations is the possibility to use a simple reverse/bind shell or being forced to use alternate methods such as a DNS Tunnel and being more noisy on the target.
Here is the idea behind our attack and how a misconfigured firewall will become our method for pivoting to a better shell.
The idea is that often a web developer will need another port opened for FTP, just a debug HTTP server at port 8080 or simply because the application owner doesn’t know which ports are required asks the firewall team to open unnecessary ports and when unused it becomes our primary target for a bindshell
Uploading the web shell
Our first obstacle is to upload the web shell. This varies greatly in what exploit you have found. In our most recent assignment we could simply upload one because we had access to a tomcat instance and with a tomcat instance you can simply upload a webshell as a .war file.
First we have to generate our .war file which we will upload
Inside the .war file we need a .jsp file in which we have our java code that takes a cmd parameter and then executes it and provides us with the results.
The command for generating a .war file is:
jar -cvf ../uniqueshellname.war uniqueshellname.jsp
This outputs the file uniqueshellname.war that we can deploy on the tomcat instance.
This is done in the following way:
Then we check that our shell works by going to
Great! We now have a working webshell. Onto finding open ports!
Checking for open inbound ports
Now we need to check for inbound ports on which we can bind our interactive shell to. This means that the port has to be allowed through the firewall but not used by the victim machine.
With a simple NMAP scan we can easily detect what ports are not in use but are open through the firewall. The reason why this is possible is because when a port is blocked by the firewall no connection is ever made and no response is given whereas if the port is open the operating system on the victims machine will send a RST packet.
The following nmap command will do the trick:
nmap -sS -p- -T4 -v --reason -oN nmap.out <target_ip>
-sS: SYN scan
-p-: Scan all ports 1-65535
-T4: Faster NMAP Scan
--reason: Force nmap to provide a reason
-oN: output to specific file
After this we get the output and we will look for “closed” ports. This is ports unused but the OS replied with a RST packet, which means that we can use them for a bind shell.
We can see that port 21 is closed. Perfect! We’re going to use this then!
So now we have everything we need in order to get a better shell/backdoor.
We’re going to generate a payload which we can used to bind on port 21
We can use
msfvenom to do the trick
msfvenom --platform Windows --p windows/shell/bind_tcp LPORT=21 -f exe > bindshell.exe
We then get a file called bindshell.exe which we can now upload to the target and run ( through our webshell ) and then connect to it.
Our job is now done and we have a shell on port 21 that we can connect to in a proper way. The payload could be anything but in this case it was just a shell.
If inbound are not doing the trick, outbound is an equally fine solution. This however can often be a bit trickier to detect because you have to check the connection from the inside and then out.
This is often done by bruteforcing or a lucky guess.
There are several methods to do it some more noisy than others.
- Bruteforce all 1-65535 ports with outgoing connections
- Bruteforce the most commonly used ports such as 21, 80, 443 etc.
- look at
netstat -nafor established connections to give an idea of what might be open
A few tools that can help you in your discovery is metasploits
reverse_tcp_allports that will do the bruteforcing for you.
We’ve briefly touched upon what challenges a pentester or an adversary faces when trying to compromise your infrastructure. Let’s try to break these challenges into solutions for a defender.
- Simply scan your public facing IP segment for closed ports (open in the perimeter firewall, but not listening on the target host). Adjust the perimeter firewall policy accordingly.
- Realtime identify when a public facing system starts listening on a new port.
- CIS Critical Security Controls #9 (Limitation and Control of Network Ports, Protocols and Services) focuses on reducing open ports. It should be of same importance to reduce closed ports.
- The perimeter firewall will never be correct. Combine host-based firewall to create a fine-grained fw policy.
- Fire an alert if your puclic facing systems starts initiating outbound connections causing a firewall drop.