Cacti RCE to Docker Desktop Escape: Anatomy of a Two-CVE Kill Chain

Two CVEs — an authenticated Cacti RCE and an unauthenticated Docker Desktop escape — chain into a full host compromise in about six commands. Anatomy of the kill chain.

Share
Cacti RCE to Docker Desktop Escape: Anatomy of a Two-CVE Kill Chain
TL;DRCVE-2025-24367 is an authenticated RCE in Cacti ≤ 1.2.28 via graph template injection into the rrdtool binary, patched in 1.2.29.CVE-2025-9074 is an unauthenticated Docker Engine API exposure on Docker Desktop for Windows and macOS (< 4.44.3), CVSS 9.3, letting any container talk to the host Docker daemon on Docker Desktop's internal subnet (default 192.168.65.7:2375).Chained together, an authenticated Cacti user on a Dockerized deployment can escape the container and mount the host filesystem with two HTTP POSTs.The HTB MonitorsFour machine weaponizes this exact chain in a lab setting, which is why it is such an instructive case study.Mitigation is cheap — patch Cacti, patch Docker Desktop, and stop treating container boundaries as trust boundaries.

Every real breach is a chain. Single vulnerabilities are the cards you're dealt; the kill chain is how you play the hand. In late 2025 two unrelated CVEs landed close enough in time that, on the right target, they stack into one of the cleanest privilege-escalation paths seen all year: from a regular Cacti login to full host compromise in about six commands.

This post breaks down that chain — CVE-2025-24367 (Cacti) into CVE-2025-9074 (Docker Desktop) — for defenders and pentesters who want to understand why it works, not just what the PoC command-line looks like. HackTheBox's MonitorsFour is the cleanest public illustration; we'll use it as the reference composition without touching flag paths, since the machine is still active at time of writing.

Why This Chain Deserves Your Attention

Cacti has been a staple of network monitoring for two decades and ships on more production networks than most infra teams want to admit. Docker Desktop has quietly become the way developers on Windows and Mac run production-like workloads locally — often with the same stack their SaaS runs on.

CVE-2025-24367 is a post-authentication flaw, normally filed under "medium risk, patch at your leisure." That changes the moment credentials leak. MonitorsFour models this realistically: an IDOR on a customer API drops unsalted MD5 hashes that crack trivially, and one is reused on the Cacti login [1]. In the wild, the credential-leak step is whatever you want — breach dumps, phishing, a forgotten .env.

CVE-2025-9074 flips the severity math entirely. Disclosed in August 2025 and patched in Docker Desktop 4.44.3, it carries a CVSS of 9.3 and — crucially — does not require a malicious container. An SSRF in any containerized web app works too. The Cacti RCE slots in neatly: it puts an attacker inside a container on the Docker Desktop host, and from there the Engine API is a curl away.

CVE-2025-24367: Newlines as a Command-Injection Primitive

The Cacti bug is textbook incomplete sanitization. The cacti_escapeshellarg function escapes shell metacharacters in graph template input but fails to handle newline characters, letting attackers inject extra directives on subsequent lines.

The vulnerable surface is the graph template editor at /cacti/graph_templates.php. When Cacti renders a graph, it hands parameters to rrdtool on the command line. Fields like right_axis_label and vertical_label flow into that invocation. Because rrdtool accepts multi-line scripts on stdin, a newline in a label turns the rest of the "label" into a fresh rrdtool directive — including one that writes a PHP file to disk via the graph subcommand's file-output capability.

An authenticated Cacti user with graph permissions can abuse this to drop arbitrary PHP scripts in the web root, leading to RCE. Fixed in 1.2.29. CVSS 7.2. Public proof-of-concept code automates the whole dance [2] — log in, pick a victim graph template, inject the payload, trigger the render, catch the reverse shell. The entire exploit fits on one screen of Python.

Three things make this nastier than CVSS suggests. First, the auth bar is low: Cacti's default permission model lets any user with graph-editing privileges reach the vulnerable code path — a much wider role than "admin." Second, Cacti concentrates blast radius: monitoring systems see everything on the network, so a shell on the Cacti box frequently has line-of-sight to routers, switches, and management VLANs. Third — and the reason we're writing this post — when Cacti runs in Docker, which is its most common modern deployment shape, an RCE inside the container is only the beginning of the hand.

CVE-2025-9074: The Docker Engine API Was Never Supposed to Be Reachable

Here's where the writeup turns from "yet another authenticated RCE" into something that should make your Docker Desktop fleet manager nervous.

The vulnerability lets any container reach the Docker Engine API at 192.168.65.7:2375 without authentication. Two HTTP POSTs compromise the host: one to /containers/create binding the host drive (/ on macOS, C:\ on Windows) to a folder in a new container with a startup command, one to /containers/{id}/start. That's it.

The root cause is architectural. On Linux, the Docker Engine talks to clients over a Unix socket (/var/run/docker.sock) with filesystem permissions acting as access control. Docker Desktop, bridging a Windows or macOS host to a Linux VM, exposes the Engine over TCP on an internal network reachable from inside containers. Docker Desktop on Linux is not affected — Linux uses a Unix socket rather than an open TCP port.

Worse, according to Docker's own security advisory, the issue persists regardless of Enhanced Container Isolation (ECI) or TCP-exposure settings [4][6], and on Windows with a WSL2 backend the flaw lets host drives be mounted with the same permissions as the Docker Desktop user. ECI is the feature Docker sells specifically to enterprises who want strong container isolation. It didn't help.

The exploit payload is almost embarrassing in its brevity:

curl -X POST http://192.168.65.7:2375/containers/create \
  -H "Content-Type: application/json" \
  -d '{
    "Image": "alpine",
    "HostConfig": {"Binds": ["/:/host_root"]},
    "Cmd": ["sh", "-c", "cp /host_root/root/.ssh/id_rsa /host_root/tmp/"]
  }'

curl -X POST http://192.168.65.7:2375/containers/{id}/start

Mount the host root into a new container, tell it to exfiltrate whatever you want on startup, press go. On Windows Docker Desktop the analogous path drops you into C:\ with the Docker Desktop user's permissions — typically the interactive user, typically a local admin.

Why the SSRF Angle Matters More Than the "Malicious Container" Angle

The headline framing of CVE-2025-9074 has been "malicious containers can escape." That's true but misleading about where the risk actually lives. An attacker can proxy malicious requests through a vulnerable application running inside a container [5][6] — any authenticated RCE or SSRF in a containerized web app becomes a full host compromise. No attacker-controlled container required. That's exactly the bridge the Cacti CVE provides.

The Full Chain, End to End

The realistic attack narrative:

  1. Initial foothold: leaked or phished credentials for a Cacti user with graph permissions. In MonitorsFour this comes from an IDOR with a classic falsy-value bypass (token=0 evaluates as missing) [1]; in the wild it's any credential-exposure event.
  2. Cacti RCE (CVE-2025-24367): authenticated user injects newline-separated rrdtool directives via a graph template, drops a PHP web shell under the Cacti web root, then hits that PHP to spawn a reverse shell.
  3. Situational awareness: shell lands as www-data inside a container. Hostname is a container ID, ip addr shows a 172.x bridge network. Mental note: you're nested.
  4. Docker escape (CVE-2025-9074): from inside the container, probe 192.168.65.7:2375. If the Engine API responds, post a container-create request with / or C:\ mounted, start it, host file access achieved.
  5. Consolidation: on Windows Docker Desktop this typically means reading the interactive user's data or dropping a startup payload. The attacker has the rights of the Docker Desktop user — in most developer setups, workstation admin.

Total shells required: one. Total CVEs: two. Total time on a realistic run: about two hours of enumeration [3]. This is the bad beat — not a zero-day nobody saw coming, but two patchable, publicly-documented CVEs chained because nobody patched the second one in time.

Detection and Mitigation: What Actually Works

The mitigations are unambiguous and cheap. Do them today.

Patch Cacti to 1.2.29 or newer. This kills the RCE primitive entirely [7]. If you can't patch immediately, audit your user base, enforce MFA on admin accounts, and put Cacti behind a VPN or access proxy.

Patch Docker Desktop to 4.44.3 or newer. This is the whole fix for CVE-2025-9074. If you manage a developer fleet, this should be an MDM-enforced minimum version, not a "please update when you can" email.

Stop trusting containers as a security boundary. Container escapes are no longer theoretical — they come from everyday misconfigurations, unpatched kernels, and small oversights that compound [8]. For workloads running untrusted or semi-trusted code, VM-based isolation via Kata Containers or gVisor raises the bar meaningfully.

Detection wins. Even fully patched, you want the telemetry. Outbound connections from an application container to a Docker Engine port (2375/2376) should be a high-fidelity alert. A web-app container spawning a new container via the Engine API is not something that happens in normal operation, ever. Runtime tools like Falco or Sysdig catch this out of the box.

For Cacti specifically, monitor the rrdtool process tree. Legitimate Cacti polling invokes rrdtool with predictable arguments from the poller process. An rrdtool invocation that writes to the web root, or has newlines in its argv, is post-exploitation.

Key Takeaways

  1. CVE-2025-24367 is an authenticated RCE in Cacti ≤ 1.2.28 via newline injection into the rrdtool graph-template code path; patched in 1.2.29.
  2. CVE-2025-9074 is an unauthenticated Docker Desktop container escape (CVSS 9.3) affecting Windows and macOS; patched in Docker Desktop 4.44.3.
  3. The two chain cleanly on any Dockerized Cacti deployment running on Docker Desktop, turning a medium-severity app bug into a full host takeover.
  4. SSRF is a sufficient entry primitive for CVE-2025-9074 — an attacker does not need their own container, just HTTP request forging inside one.
  5. Defense is patching plus telemetry: upgrade both components, then alert on any container-to-Engine-API traffic as a post-exploitation signal.

FAQ

Is CVE-2025-9074 exploitable on Docker for Linux? No. Docker Desktop on Linux is not affected because Linux uses a Unix socket for Docker Engine communication rather than an open TCP port. The issue is specific to Docker Desktop's architecture on Windows and macOS.

Does Enhanced Container Isolation (ECI) block CVE-2025-9074? No. The flaw persists regardless of Enhanced Container Isolation or TCP exposure settings. Enterprises paying for ECI should still patch.

Can CVE-2025-24367 be exploited without valid credentials? No. It is an authenticated RCE — the attacker must have a Cacti user with graph-template permissions. In practice, credential-reuse and unsalted-hash attacks make this a low bar on many deployments.

What's the realistic blast radius of chaining these two? Full compromise of the Docker Desktop host at the privileges of the interactive user. On typical developer workstations that's local admin, with access to source code, SSH keys, cloud credentials, and anything else sitting on disk.

Are there known in-the-wild exploits? No widely reported in-the-wild exploitation has surfaced at time of writing, though public PoCs exist for both CVEs. Given how trivial the chain is, treat detection as the priority regardless.

Sources

[1] Solrikk. "HTB Season Gacha | MonitorsFour — The Full Path from IDOR to Docker Desktop escape (WSL2) and root." Medium, December 2025. https://solrikk.medium.com/htb-season-gacha-monitorsfour-the-full-path-from-idor-to-docker-desktop-escape-wsl2-and-root-de2de2f5062a

[2] GitHub Advisory. "Cacti allows Arbitrary File Creation leading to RCE (GHSA-fxrq-fr7h-9rqq)." https://github.com/Cacti/cacti/security/advisories/GHSA-fxrq-fr7h-9rqq

[3] CodeBlackwell. "MonitorsFour — From Zero to Docker Desktop Escape." Medium, January 2026. https://medium.com/@CodeBlackwell/monitorsfour-from-zero-to-docker-desktop-escape-af1b2522de35

[4] The Hacker News. "Docker Fixes CVE-2025-9074, Critical Container Escape Vulnerability With CVSS Score 9.3." August 2025. https://thehackernews.com/2025/08/docker-fixes-cve-2025-9074-critical.html

[5] CSO Online. "Critical Docker Desktop flaw allows container escape." August 2025. https://www.csoonline.com/article/4046353/critical-docker-desktop-flaw-allows-container-escape.html

[6] SOCRadar. "CVE-2025-9074: Docker Desktop Vulnerability Allows Host Compromise." https://socradar.io/blog/cve-2025-9074-docker-desktop-host-compromise/

[7] Wiz. "CVE-2025-24367 Impact, Exploitability, and Mitigation Steps." https://www.wiz.io/vulnerability-database/cve/cve-2025-24367

[8] Fidelis Security. "What is Docker Container Escape?" November 2025. https://fidelissecurity.com/cybersecurity-101/cloud-security/what-is-docker-container-escape/