Mentor
Last updated
Last updated
Publicado: 23 de Mayo de 2025 Autor: José Miguel Romero aKa x3m1Sec Dificultad: ⭐ Medium
Mentor es una máquina Linux de dificultad media que presenta múltiples vectores de ataque y técnicas de enumeración. La máquina aloja una aplicación web Flask que permite a los usuarios escribir citas motivadoras, complementada con una API REST documentada.
La explotación inicial requiere una enumeración exhaustiva que incluye el descubrimiento de servicios SNMP en el puerto 161/UDP, donde mediante fuerza bruta se obtienen credenciales válidas almacenadas en strings de comunidad. Paralelamente, el fuzzing de virtual hosts revela un subdominio API (api.mentorquotes.htb
) que expone endpoints administrativos protegidos por autenticación JWT.
El vector de ataque principal involucra la autenticación en la API utilizando credenciales obtenidas via SNMP, seguido del abuso de una funcionalidad de backup vulnerable a inyección de comandos. Esta vulnerabilidad permite ejecutar código remoto y obtener acceso inicial al sistema, aunque se descubre que el acceso es a un contenedor Docker.
La escalada de privilegios requiere técnicas de pivoting mediante port forwarding (utilizando ligolo-ng) para acceder a una base de datos PostgreSQL interna. Las credenciales extraídas de la base de datos permiten el acceso SSH al host real, y la escalada final se logra mediante el descubrimiento de credenciales adicionales en archivos de configuración SNMP y el abuso de permisos sudo mal configurados.
Vectores de ataque principales:
Enumeración SNMP y fuerza bruta de community strings
Fuzzing de virtual hosts y descubrimiento de APIs
Inyección de comandos en endpoint de backup
Pivoting desde contenedor Docker al host principal
Escalada mediante credenciales en archivos de configuración
Abuso de permisos sudo
💡 Nota: El TTL cercano a 64 sugiere que probablemente sea una máquina Linux.
⚠️ Importante: Detectamos durante la fase de enumeración con nmap que se está realizando virtual hosting. Debemos añadir el siguiente vhost a nuestro fichero /etc/hosts
En primer lugar podemos hacer fuerza bruta para descubrir distintos strings de comunidades
Nos genera un fichero bastante extenso con todas las strings pero tras una enumeración profunda descubrimos algo que podría sernos útil y que podría ser una credencial porque se está usando con un script en python llamado login.py:
Enumerando el servicio web del puerto 80 de forma manual, no vemos gran cosa aparte de un portal donde los usuarios escriben citas motivadoras:
Enumeramos las tecnologías usando wappalyzer y vemos que está construida con python 3 y Flask:
Interceptamos la petición con Burpsuite y encontramos en la respuesta que el server es Werkzeug 2.0.3
No hallamos ningún recurso realizando fuzzing de directorios con gobuster y feroxbuster.
Durante la realización del fuzzing de vhost, es importante destacar que tuve que ajustar el comando usando varios diccionarios y añadiendo finalmente la opción -mc all, la cual fue clave para que obtenga cualquier tipo de código de respuesta:
Halló un recureso api con un código de respuesta 404
Añadimos este nuevo vhost api.mentorquotes.htb
al fichero /etc/hosts
Volvemos a realizar fuzzing de directorios sobre el nuevo vhost descubierto:
Encontramos varios recursos:
http://api.mentorquotes.htb/admin/
http://api.mentorquotes.htb/users/
http://api.mentorquotes.htb/docs
Uno de los recursos descubiertos contiene documentación sobre la API:
http://api.mentorquotes.htb/docs
Apuntamos este usuario por si pudiese sernos de utilidad.
Vamos a jugar con la API para ver si podemos encontrar un vector de ataque. Atacamos el endpoint de login usando el usuario que hemos obtenido "james" y usamos como contraseña el valor encontrado en la string de snmp:
Vemos que el servicio nos responde con lo que podría ser un token:
Existe otro endpoint /users que requiere de especificar una cadena de autorización para poder usarlo, probemos con el token que hemos obtenido:
Construimos la petición GET con curl especificando el token en la cabecera de autorización y hacemos un pipe de jq para formatear la salida a formato JSON para una mejor visualización de la salida:
Por otro lado, si vamos al endpoint /admin e interceptamos la petición con burp y añadimos la cabecera de autorización con el token obtenido:
Vemos en la respuesta que parece que hay un par de funciones de administración:
Repetimos la misma operación con cada uno de ellos:
/check
Parece que esta función aún no ha sido implementada y nos sirve de utilidad.
/backup
Esta nos indica que el tipo de petición no está permitida, cambiemos el GET por un POST:
Ahora nos falla porque el servicio espera que le enviemos como parámetro un JSON que tenga esa estructura con un body.
Añadimos primeo la cabecera content-type: application/json y metemos un json vacío
Ahora que ya sabemos la estructura que espera el servicio, la pasamos en la llamada:
Vemos que el servicio devuelve un DONE!, por lo que a priori parece haber ido bien.
Podemos abusar de esta petición para intentar ejecutar un RCE . Veamos primero si el parámetro path es vulnerable a inyección de comandos
Iniciamos la captura de tráfico de protocolo icmp
Usamos el siguiente payload mediante el uso del carácter ; para ejecutar la inyección de comandos:
Interceptamos la petición ping a nuestro host, luego la inyección funciona y validamos la prueba de concepto.
Iniciamos un listener
Veamos ahora como podría llevar a cabo esto con una shell one liner para llevar a cabo un RCE:
Ganamos acceso a la máquina. Al principio parece que nuestro objetivo es doble, porque somo root, pero pronto nos damos cuenta de que estamos dentro de un contenedor de docker
Obtenemos la primera flag en el directorio /home/svc
Enumeramos la máquina y descubrimos un archivo db.py en el directorio /app/app:
Para ganar acceso a la base de datos, necesitamos realizar port forwading, en este caso no podemos usar ssh porque no tenemos ninguna clave privada con la que podes conectarnos usando este protocolo, lo haremos usando ligolo-ng
Descargamos ligolo tanto el proxy como el cliente
Definimos una interfaz para ligolo
Levantamos la interfaz
Iniciamos el proxy en el host de ataque
Transferimos el agente al host destino, le damos permisos de ejecución y lo ejecutamos
Ahora añadimos un listener para realizar el redireccionamiento
A continuación usamos el siguiente comando para conectarnos a la base de datos
El hash está en md5, obtenemos la contraseña:
Ahora nos conectamos a través del protocolo ssh usando el usuario svc y la contraseña obtenida:
Escalada a usuario james
Buscamos ahora la escalada de privilegios
Transferimos la herramienta linpeas.sh al directorio /tmp de la máquina objetivo, le damos permisos de ejecución y ejecutamos.
Revisando el archivo /etc/snmp/snmpd.conf encontramos una credencial:
Escalada a root
Nos autenticamos como james usando la contraseña obtenida en el fichero snmpd.conf y logramos escalar a este usuario. A continuación, verificamos si puede ejecutar algún comando como root:
En este caso, vemos que james puede ejecutar una shell como root, por lo que la escalada es muy sencilla y basta con hacer lo siguiente:
![[Pasted image 20250523141535.png]]