githubEditar

HackTheBox - Analytics

Writeup de la máquina Analytics de HackTheBox

  • 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:

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_  256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://analytical.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
# Nada relevante en UDP

Añadimos analytical.htb a /etc/hosts.

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.

gobuster vhost --url http://analytical.htb -w /usr/share/wordlists/seclists/Discovery/DNS/n0kovo_subdomains.txt --append-domain
===============================================================
Gobuster v3.8
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                       http://analytical.htb
[+] Method:                    GET
[+] Wordlist:                  /usr/share/wordlists/seclists/Discovery/DNS/n0kovo_subdomains.txt
[+] Append Domain:             true
===============================================================
Starting gobuster in VHOST enumeration mode
===============================================================
data.analytical.htb Status: 200 [Size: 77858]

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.com

    • due@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.

HTTP: 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-38646arrow-up-right."

Como no vemos nada relevante en /api, probamos a buscar algún exploit público y encontramos estearrow-up-right.

Al ejecutarlo con penelopearrow-up-right 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: root y metabase

  • 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:kal

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. Este error solo me ha costado 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)arrow-up-right, así que usamos el exploit correspondiente:

Y tenemos root.

Post-Root: GameOver(lay)

GameOver(lay)arrow-up-right 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:

  1. Capa superior (Read/Write)

  2. 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:

  1. 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).

  2. El atacante monta en la capa inferior (ro) un FS que controla completamente con un archivo malicioso (p.ej bash, con owner root y CAP_SETUID).

  3. 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).

  4. 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.

  5. Ahora, en el sistema real, hay un binario de bash, perteneciente a root y com CAP_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.

Última actualización