The purpose of this article is to discuss ways to troubleshoot and diagnose common issues encountered during penetration tests.
I hope to extend this article as much as possible as I receive feedback from other pentesters.
Seeing errors in non-interactive shells
I often find myself with a low-privileged non-interactive shell on Linux/Unix hosts. An example of this could be a web-based shell using something like PHP, or even a netcat shell.
One problem with non-interactive shells is that you are only redirecting STDIN and STDOUT. You are unable to see STDERR, which is where all the juicy compile and execution errors would go. However we can simply redirect standard error to a text file and read the contents.
The following is an example of us trying to execute a binary on a target system.
$ ./localr00texploit $ whoami andrew
Ouch. Unfortauntely, the binary didn't execute. Let's redirect to standard error and figure out why...
$ ./localr00texploit 2> errors.txt $ cat errors.txt bash: line 20: ./localr00texploit: Permission denied
Ahh there's our problem. Now that we've diagnosed the problem, we can run chmod +x and go on our merry way.
Note: It's also possible (and probably much more convenient) to simply spawn a pseudo terminal with Python in this scenario. This can be done using the following command:
python -c 'import pty; pty.spawn("/bin/bash")' [email protected]:~$ [email protected]:~$ [email protected]:~$
This will turn your plain-jane netcat session into a quasi-interactive shell, equipped with STDERR. I'm almost positive it's possible to pass ctrl-c signals also, but I can't remember how. If you know how, please shoot me an email.
Detecting firewalls with Nmap
It it important to ensure a clear network path between you and your target machine before launching any exploits. If you attempt to exploit a vulnerable machine and use a reverse shell payload and all egress traffic is blocked by a local firewall then you're out of luck.
The following is a fairly reliable method I've used to identify firewalls on a target machine.
Let's compare Nmap output when scanning a blocked port versus a closed (but accessible) port:
# iptables -A INPUT -p tcp --destination-port 12345 -j DROP
[email protected]:~# nmap -P0 -vvv -p 12345 --reason andrewmorris.xxx PORT STATE SERVICE REASON 12345/tcp filtered netbus no-response
Let's compare this with an unblocked and closed port.
[email protected]:~# nmap -P0 -vvv -p21 --reason andrewmorris.xxx PORT STATE SERVICE REASON 21/tcp closed ftp conn-refused
Notice that when we scan a port that is unblocked, but closed, Nmap outputs that the connection was refused. This is due to the completion of the TCP handshake. As per RFC-793, when a TCP port receives a connection attempt (TCP SYN), it sends an RST to indicate it is not in a listening state.
To summarize: if the port is not blocked by a firewall, the server will respond with a packet regardless of whether it is listening or not. Place your bind shells accordingly.
Stateful network firewalls will sometimes respond to connection attempts with RSTs, as opposed to dropping the packets.