- Dificultad:
easy - Tiempo aprox.
~2.5h - Datos Iniciales:
10.129.229.224
Nmap Scan y enumeración#
Tras realizar un escaneo nmap, se encuentran los siguientes puertos abiertos:
| |
Añadimos analytical.htb a /etc/hosts.
Nota: Redirecciones
El hecho de que http nos redirija a analytical.htb indica que la configuración del servidor web utiliza vhosts para saber qué servir al usuario (Y por tanto, si accedes a la IP tal cual, el servidor no sabe qué servirte, por eso nos ha redirigido). Una vez que sabes que el servidor discrimina por nombres, la probabilidad de que existan otros nombres (subdominios/vhosts) en esa misma IP se eleva bastante. De ahí que el siguiente paso que tomo sea un análisis con gobuster.
| |
Y hemos encontrado data.analytical.htb, lo añadimos también a /etc/hosts.
HTTP#
analytical.htb#
Antes de entrar directamente al subdominio data, vamos a analytical.htb. No encontramos nada relevante en la página principal, salvo:
- Nombres de trabajadores (Probablemente sean decoración, pero podrían servir para crear wordlists de usuarios).
- Jonnhy Smith
- Alex Kirigo
- Daniel Walker
- Emails (probablemente no válidos):
demo@analytical.comdue@analytical.com
Además, encontramos un botón Login que nos redirige a data.analytical.htb, subdominio que ya conocíamos. De ahora en adelante nos centramos en data.analytical.htb.
data.analytical.htb#
Se trata de un subdominio que corresponde a un servicio de Metabase. Tras buscar en Internet:
Metabase is an open-source business intelligence (BI) tool that allows users to explore and visualize data from various databases, creating interactive dashboards and reports without needing SQL knowledge.
En la página de login no encontramos ninguna información de versión ni del servidor:

Además, tras buscar en google:
“Metabase does not have hardcoded default credentials like “admin/password” for initial setup. Instead, it forces you to create the first admin account upon the very first launch.”
Por lo que no hay mucho que podamos probar.
Intentamos enumerar subdirectorios:
| |
Nos encontramos un wildcard para archivos y subdirectorios. Además, no podemos filtrar por tamaño porque en cada solicitud los bytes de respuesta varían un poco (+-40B).
Pruebo a enumerar manualmente algunos directorios comunes, teniendo en cuenta que para cualquier elemento que no existe se devuelve la página de login.
Para /api/:

Vemos que se devuelve "API endpoint does not exist.", así que probamos a enumerar el directorio api:
| |
Vemos que data.analytical.htb/api/health devuelve HTTP/200, probamos a acceder al endpoint:
| |
Tras buscar en /api con distintos métodos HTTP (POST/PUT/OPTIONS…) seguimos sin encontrar nada.
Vuelvo a mirar en la página web de login y veo que, en los datos devueltos, se encuentra lo siguiente:
| |
Tanto el tag como el hash apuntan a la misma versión de Metabase: v0.46.6
“Metabase v0.46.6 tiene una vulnerabilidad crítica de ejecución remota de código (RCE) sin autenticación, identificada como CVE-2023-38646.”
Como no vemos nada relevante en /api, probamos a buscar algún exploit público y encontramos este.
Al ejecutarlo con penelope en escucha:
| |
Como decía la página del PoC, para conseguir el setup-token (-t) vamos a
/api/session/properties.
Y en el handler:
| |
Salida de Docker#
Enumeración#
Ejecutamos linpeas y encontramos varias cosas relevantes:
- Estamos en un container Docker.
Rootless Docker? No
- 2 usuarios con consola:
rootymetabase - MUY IMPORTANTE:
/proc mounted? Yes - IMPORTANTE: Archivos cambiados recientemente:
/metabase.db/metabase.db.mv.db/tmp/hsperfdata_metabase/1
- IMPORTANTE: Archivos/directorios inesperados en root:
/plugins,/app,/metabase.db,/.dockerenv
- IMPORTANTE: Puerto abierto:
0.0.0.0:3000 java(Metabase)
- IMPORTANTE: Common host filesystem mounted?
- /dev/sda2 on /etc/hostname type ext4 (rW,relatime)
- /dev/sda2 on /etc/hosts type ext4 (rw,relatime)
- IMPORTANTE: Dangerous capabilities
- CapBnd: 00000000a00425f9
Además, al ejecutar env encontramos credenciales:
| |
Después de una hora descartando las opciones de arriba y tras haber probado al principio a conectarme por SSH con las credenciales, vuelvo a intentar iniciar sesión por ssh:
| |
Resulta que la primera vez había escrito mal el usuario metalytics, tal error solo me costó una hora de mi tiempo.
Privesc#
Ejecutamos linpeas ya fuera del entorno docker, encontramos que nuestra versión del kernel es 6.2.0-25-generic, 22.04.3 LTS (Jammy Jellyfish):
| |
Tras una búsqueda, vemos que esta versión específica es vulnerable a GameOver(lay), así que usamos el exploit correspondiente:
| |
Y tenemos root.
Post-Root: GameOver(lay)#
GameOver(lay) es el nombre de una vulnerabilidad de privesc local de Ubuntu y derivados.
OverlayFS & User Namespaces#
El nombre viene de OverlayFS, el componente afectado. Es un sistema de archivos que permite superponer otros dos:
- Capa superior (Read/Write)
- Capa inferior (Read Only)
OverlayFS pone una sobre otra y las fusiona, el sistema obtiene una vista unificada.
Si lees un archivo, lo ves desde abajo; si intentas modificar un archivo de abajo, el sistema primero hace una copia exacta en la capa de arriba (copy-up) y luego aplica los cambios.
Esto se usa mucho en containers, p.ej, de Docker (como el que había en la Analytics).
Por otro lado, los User Namespaces (en relación a esto) son una herramienta del kernel de Linux que permite que un proceso tenga un UID específico dentro de un entorno aislado, y otro en el sistema real. Dentro del entorno, si eres root, puede actuar como root, pero una vez sales vuelves a ser el usuario que eres en realidad.
El kernel de Linux era bastante estricto con OverlayFS, y solo permitía que el root del host OS (no dentro de un User Namespace) montase un filesystem OverlayFS, pero Ubuntu, en 2018, añadió modificaciones en el módulo de OverlayFS del kernel de Linux para que los usuarios que eran root dentro de un Namespace también pudiesen montar OverlayFS, con el fin de que los usuarios normales pudiesen lanzar containers sin necesidad de ser root real.
Vulnerabilidad#
El cambio realizado por Ubuntu no supuso una vulnerabilidad hasta 2 años más tarde, cuando otro parche diferente creó un vector de escalada. Ahora, podía pasar lo siguiente:
- El atacante (no privilegiado) crea un User Namespace y se hace root del mismo. Ahí dentro monta un sistema OverlayFS (gracias al parche de Ubuntu).
- El atacante monta en la capa inferior (ro) un FS que controla completamente con un archivo malicioso (p.ej bash, con owner
rootyCAP_SETUID). - El atacante intenta modificar ese archivo malicioso. OverlayFS inicia el proceso de copy-up para llevarlo a la capa superior (que es una carpeta real del sistema).
- El kernel ve que el usuario es root, aunque en su namespace, pero le vale porque no hay comprobaciones de seguridad, y copia el archivo con todos sus atributos intactos.
- Ahora, en el sistema real, hay un binario de
bash, perteneciente arooty comCAP_SETUID.
Esta vulnerabilidad existió (y existe) porque, en el momento de hacer la modificación, los desarrolladores de Ubuntu no pensaron en añadir una comprobación a la hora de hacer copy-up.
El kernel de Linux original no necesitaba hacer comprobaciones porque en ningún caso un usuario normal podía llegar a una situación como la que permitía el de Ubuntu, si habías llegado hasta el punto de hacer copy-up habiendo montado OverlayFS, se podía asumir que, en circunstancias normales, eras root global.




