SMTP (Simple Mail Transfer Protocol)
El Protocolo Simple de Transferencia de Correo (SMTP) es un protocolo para enviar correos electrónicos en una red IP. Puede utilizarse entre un cliente de correo electrónico y un servidor de correo saliente, o entre dos servidores SMTP. SMTP se combina a menudo con los protocolos IMAP o POP3, que se encargan de recuperar los correos. En principio, es un protocolo basado en cliente-servidor, aunque SMTP puede utilizarse entre un cliente y un servidor, y entre dos servidores SMTP; en este último caso, el servidor actúa como cliente.
Configuración por defecto (Postfix)
❯ cat /etc/postfix/main.cf | grep -v "#" | sed -r "/^\s*$/d"
smtpd_banner = ESMTP Server
biff = no
append_dot_mydomain = no
readme_directory = no
compatibility_level = 2
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
myhostname = mail1.domain.local
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
smtp_generic_maps = hash:/etc/postfix/generic
mydestination = $myhostname, localhost
masquerade_domains = $myhostname
mynetworks = 127.0.0.0/8 172.16.59.0/24
mailbox_size_limit = 0
recipient_delimiter = +
smtp_bind_address = 0.0.0.0
inet_protocols = ipv4
smtpd_helo_restrictions = reject_invalid_hostname
home_mailbox = /home/postfixmynetworks: define qué redes pueden usar el servidor como relay sin autenticación; un rango demasiado amplio aquí es una configuración peligrosa (ver sección de Open Relay más abajo).smtpd_helo_restrictions: puede usarse para rechazar clientes que envíen un hostname inválido en el saludo HELO/EHLO.
Comandos del protocolo SMTP
| Comando | Descripción |
|---|---|
AUTH PLAIN | Extensión de servicio utilizada para autenticar al cliente. |
HELO | El cliente inicia sesión con el nombre de su computadora. |
MAIL FROM | El cliente nombra el remitente del correo electrónico. |
RCPT TO | El cliente nombra el destinatario del correo electrónico. |
DATA | El cliente inicia la transmisión del correo electrónico. |
RSET | El cliente aborta la transmisión iniciada pero mantiene la conexión. |
VRFY | El cliente comprueba si hay un buzón disponible para la transferencia de mensajes. |
EXPN | El cliente verifica si hay un buzón disponible para enviar mensajes (similar a VRFY, pero para listas de distribución). |
NOOP | El cliente solicita una respuesta del servidor para evitar la desconexión por tiempo de espera. |
QUIT | El cliente finaliza la sesión. |
Telnet - HELO/EHLO
❯ telnet 172.16.59.10 25
Trying 172.16.59.10...
Connected to 172.16.59.10.
Escape character is '^]'.
220 ESMTP Server
HELO mail1.domain.local
250 mail1.domain.local
EHLO mail1
250-mail1.domain.local
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250-SMTPUTF8
250 CHUNKINGEHLO(Extended HELLO) devuelve además la lista de extensiones soportadas por el servidor (útil para saber si soportaAUTH, tamaño máximo de mensaje, STARTTLS, etc.).
Telnet - Enumeración de usuarios con VRFY
❯ telnet 172.16.59.10 25
Trying 172.16.59.10...
Connected to 172.16.59.10.
Escape character is '^]'.
220 ESMTP Server
VRFY root
252 2.0.0 root
VRFY agarcia
252 2.0.0 agarcia
VRFY testuser
252 2.0.0 testuser
VRFY aaaaaaaaaaaaaaaaaaaaaaaaaaaa
252 2.0.0 aaaaaaaaaaaaaaaaaaaaaaaaaaaa- El código
252no confirma que el buzón exista, pero indica que el servidor aceptará y hará el intento de entrega — esto puede usarse igualmente para diferenciar usuarios válidos de inválidos en servidores mal configurados (comparar con el código550de "usuario desconocido"). - Este servidor en particular acepta cualquier usuario con
252, lo que limita la utilidad de VRFY aquí; en servidores más estrictos, VRFY sí distingue usuarios reales de inexistentes.
Alternativa con Netcat
nc sirve igual de bien que telnet para esta interacción, y suele estar disponible por defecto donde telnet a veces no lo está:
❯ nc -nv 172.16.59.10 25
(UNKNOWN) [172.16.59.10] 25 (smtp) open
220 mail ESMTP Postfix (Ubuntu)
VRFY root
252 2.0.0 root
VRFY idontexist
550 5.1.1 <idontexist>: Recipient address rejected: User unknown in local recipient table
^C- Misma lógica que con Telnet:
252para usuarios que el servidor acepta,550para buzones inexistentes.
Automatizar VRFY con un script en Python
#!/usr/bin/python
import socket
import sys
if len(sys.argv) != 3:
print("Usage: vrfy.py <username> <target_ip>")
sys.exit(0)
# Create a Socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect to the Server
ip = sys.argv[2]
connect = s.connect((ip,25))
# Receive the banner
banner = s.recv(1024)
print(banner)
# VRFY a user
user = (sys.argv[1]).encode()
s.send(b'VRFY ' + user + b'\r\n')
result = s.recv(1024)
print(result)
# Close the socket
s.close()❯ python3 smtp.py root 172.16.59.10
b'220 mail ESMTP Postfix (Ubuntu)\r\n'
b'252 2.0.0 root\r\n'
❯ python3 smtp.py johndoe 172.16.59.10
b'220 mail ESMTP Postfix (Ubuntu)\r\n'
b'550 5.1.1 <johndoe>: Recipient address rejected: User unknown in local recipient table\r\n'- Este script puede combinarse con una wordlist de nombres de usuario comunes para automatizar la enumeración completa de cuentas válidas en el servidor.
Footprinting del servicio con Nmap
❯ sudo nmap 172.16.59.10 -sC -sV -p25
Starting Nmap 7.80 ( https://nmap.org ) at 2021-09-27 17:56 CEST
Nmap scan report for 172.16.59.10
Host is up (0.00025s latency).
PORT STATE SERVICE VERSION
25/tcp open smtp Postfix smtpd
|_smtp-commands: mail1.domain.local, PIPELINING, SIZE 10240000, VRFY, ETRN, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8, CHUNKING,
MAC Address: 00:00:00:00:00:00 (VMware)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 14.09 secondsEnumeración de usuarios directamente con el script NSE de Nmap (automatiza lo mismo que el script de Python, usando una wordlist):
❯ nmap -p25 --script smtp-enum-users --script-args smtp-enum-users.methods={VRFY} 172.16.59.10--script-args smtp-enum-users.methods=: permite elegir el método de enumeración (VRFY,EXPNoRCPT), útil si uno de los tres está deshabilitado pero otro no.
Comprobar soporte y configuración de STARTTLS
❯ openssl s_client -connect 172.16.59.10:25 -starttls smtp- Permite ver el certificado SSL/TLS ofrecido por el servidor (que puede filtrar el hostname interno real, como se vio en el archivo de FTP) y confirmar si el cifrado está bien configurado o si acepta cifrados débiles/obsoletos.
Pruebas de envío con swaks (Swiss Army Knife for SMTP)
swaks es una herramienta dedicada a probar servidores SMTP: envío de correos de prueba, autenticación, STARTTLS, e incluso pruebas de spoofing:
❯ swaks --to victima@domain.local --from atacante@externo.com --server 172.16.59.10- Útil para validar de forma más completa y controlada hallazgos como el open relay, o para probar si el servidor permite falsificar el remitente sin que SPF/DKIM lo bloqueen.
Comprobar si el servidor es un Open Relay
Un servidor mal configurado que reenvía correo de/para cualquier dominio (sin autenticación) puede ser abusado para enviar spam o phishing haciéndolo pasar por la organización objetivo:
❯ sudo nmap 172.16.59.10 -p25 --script smtp-open-relay -v
Starting Nmap 7.80 ( https://nmap.org ) at 2021-09-30 02:29 CEST
NSE: Loaded 1 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 02:29
Completed NSE at 02:29, 0.00s elapsed
Initiating ARP Ping Scan at 02:29
Scanning 172.16.59.10 [1 port]
Completed ARP Ping Scan at 02:29, 0.06s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 02:29
Completed Parallel DNS resolution of 1 host. at 02:29, 0.03s elapsed
Initiating SYN Stealth Scan at 02:29
Scanning 172.16.59.10 [1 port]
Discovered open port 25/tcp on 172.16.59.10
Completed SYN Stealth Scan at 02:29, 0.06s elapsed (1 total ports)
NSE: Script scanning 172.16.59.10.
Initiating NSE at 02:29
Completed NSE at 02:29, 0.07s elapsed
Nmap scan report for 172.16.59.10
Host is up (0.00020s latency).
PORT STATE SERVICE
25/tcp open smtp
| smtp-open-relay: Server is an open relay (16/16 tests)
| MAIL FROM:<> -> RCPT TO:<relaytest@nmap.scanme.org>
| MAIL FROM:<antispam@nmap.scanme.org> -> RCPT TO:<relaytest@nmap.scanme.org>
| MAIL FROM:<antispam@ESMTP> -> RCPT TO:<relaytest@nmap.scanme.org>
| MAIL FROM:<antispam@[172.16.59.10]> -> RCPT TO:<relaytest@nmap.scanme.org>
| MAIL FROM:<antispam@[172.16.59.10]> -> RCPT TO:<relaytest%nmap.scanme.org@[172.16.59.10]>
| MAIL FROM:<antispam@[172.16.59.10]> -> RCPT TO:<relaytest%nmap.scanme.org@ESMTP>
| MAIL FROM:<antispam@[172.16.59.10]> -> RCPT TO:<"relaytest@nmap.scanme.org">
| MAIL FROM:<antispam@[172.16.59.10]> -> RCPT TO:<"relaytest%nmap.scanme.org">
| MAIL FROM:<antispam@[172.16.59.10]> -> RCPT TO:<relaytest@nmap.scanme.org@[172.16.59.10]>
| MAIL FROM:<antispam@[172.16.59.10]> -> RCPT TO:<"relaytest@nmap.scanme.org"@[172.16.59.10]>
| MAIL FROM:<antispam@[172.16.59.10]> -> RCPT TO:<relaytest@nmap.scanme.org@ESMTP>
| MAIL FROM:<antispam@[172.16.59.10]> -> RCPT TO:<@[172.16.59.10]:relaytest@nmap.scanme.org>
| MAIL FROM:<antispam@[172.16.59.10]> -> RCPT TO:<@ESMTP:relaytest@nmap.scanme.org>
| MAIL FROM:<antispam@[172.16.59.10]> -> RCPT TO:<nmap.scanme.org!relaytest>
| MAIL FROM:<antispam@[172.16.59.10]> -> RCPT TO:<nmap.scanme.org!relaytest@[172.16.59.10]>
|_ MAIL FROM:<antispam@[172.16.59.10]> -> RCPT TO:<nmap.scanme.org!relaytest@ESMTP>
MAC Address: 00:00:00:00:00:00 (VMware)
NSE: Script Post-scanning.
Initiating NSE at 02:29
Completed NSE at 02:29, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.48 seconds
Raw packets sent: 2 (72B) | Rcvd: 2 (72B)smtp-open-relayprueba 16 combinaciones distintas deMAIL FROM/RCPT TOpara intentar burlar posibles filtros; si todas pasan (16/16 tests), el servidor es un open relay confirmado.nmap.scanme.orges el dominio de pruebas oficial de Nmap, usado como destinatario "externo" ficticio en la prueba — no pertenece al objetivo escaneado.
Enumeración manual de un Open Relay
Una vez confirmado que el servidor es un relay abierto, se puede validar manualmente enviando un correo de prueba desde/hacia dominios externos:
❯ telnet 172.16.59.10 25
HELO test
MAIL FROM: attacker@external-domain.com
RCPT TO: victim@another-external-domain.com
DATA
Subject: prueba de open relay
Este correo demuestra que el servidor reenvia correo de dominios externos sin autenticacion.
.
QUIT- Si el servidor responde
250 OKen cada paso sin exigir autenticación, confirma el relay abierto de forma manual, sin depender del script de Nmap.
SMTP desde un cliente Windows
En un escenario de post-explotación donde solo se dispone de un host Windows (sin Kali disponible), también se puede enumerar SMTP recurriendo a herramientas nativas o instalables sin conexión a internet.
Comprobar el puerto con Test-NetConnection
PS C:\Users\student> Test-NetConnection -Port 25 172.16.59.10
ComputerName : 172.16.59.10
RemoteAddress : 172.16.59.10
RemotePort : 25
InterfaceAlias : Ethernet0
SourceAddress : 172.16.59.15
TcpTestSucceeded : True- Confirma que el puerto está abierto, pero
Test-NetConnectionno permite interactuar con el protocolo SMTP en sí (no se puede enviarVRFY,HELO, etc. con esta función).
Instalar el cliente Telnet de Windows
Windows no trae Telnet habilitado por defecto, pero puede activarse como característica opcional (requiere privilegios administrativos):
PS C:\Windows\system32> dism /online /Enable-Feature /FeatureName:TelnetClient- Si no se cuenta con privilegios de administrador para habilitar la característica, se puede copiar directamente el binario
C:\windows\system32\telnet.exedesde otra máquina Windows (por ejemplo, una de desarrollo propia) y transferirlo al host desde el que se está enumerando — evitando así la necesidad de privilegios elevados.
Enumerar usuarios por VRFY desde Windows
Una vez disponible Telnet, la interacción es idéntica a la que se haría desde Kali:
C:\Windows\system32>telnet 172.16.59.10 25
220 mail ESMTP Postfix (Ubuntu)
VRFY goofy
550 5.1.1 <goofy>: Recipient address rejected: User unknown in local recipient table
VRFY root
252 2.0.0 root- Este flujo (detectar el puerto con PowerShell, habilitar o transferir Telnet, interactuar manualmente) es un buen ejemplo de "Living off the Land": hacer reconocimiento completo de un servicio sin depender de herramientas externas cuando solo se tiene acceso a un host Windows comprometido.
Explotación adicional
SMTP Smuggling
Técnica descubierta en 2023 que abusa de diferencias en cómo distintos servidores SMTP interpretan el final de los datos de un mensaje (la secuencia \r\n.\r\n). Un servidor de salida puede interpretar el fin del mensaje en un punto distinto al servidor de entrada, permitiendo "contrabandear" un segundo correo dentro del cuerpo del primero:
MAIL FROM:<atacante@externo.com>
RCPT TO:<victima@domain.com>
DATA
Asunto: correo normal
Este es un correo legitimo.
.
MAIL FROM:<ceo@domain.com>
RCPT TO:<empleado@domain.com>
DATA
Asunto: transferencia urgente
Correo "inyectado" que el servidor de entrada procesa como si viniera del dominio interno.
.
QUIT- El resultado es que el segundo mensaje puede llegar como si proviniera de
ceo@domain.com, incluso pasando SPF/DKIM/DMARC, porque el servidor receptor lo procesa como un mensaje separado y legítimo del dominio. - Es una técnica de spoofing de remitente más sofisticada que el spoofing tradicional; depende de la combinación específica de implementaciones SMTP (por ejemplo, Postfix como saliente + Exchange/Sendmail como entrante, u otras combinaciones documentadas como vulnerables).
Enumeración de usuarios por tiempo de respuesta (cuando VRFY está deshabilitado)
Si el administrador deshabilitó VRFY pensando que eso previene la enumeración, a veces sigue siendo posible diferenciar usuarios válidos de inválidos midiendo el tiempo de respuesta durante RCPT TO, ya que el servidor puede tardar más en rechazar un buzón inexistente (por validaciones adicionales) que uno que sí existe:
❯ time (echo -e "HELO test\nMAIL FROM:<test@test.com>\nRCPT TO:<jsmith@domain.local>\nQUIT" | nc -q1 172.16.59.10 25)- Comparando los tiempos de respuesta entre un usuario que se sabe válido y uno inventado, se puede inferir la validez de otros usuarios sin depender de
VRFY/EXPN. - Esta técnica es menos confiable que VRFY directo y depende de la latencia de red, por lo que conviene repetir la medición varias veces por usuario para reducir el margen de error.