In the SMTP protocol (RFC 5321), an empty MAIL FROM address (<>
) is actually a valid construct. This originates from the early days of email when bounce messages needed to be delivered without creating mail loops. The specification explicitly states:
MAIL FROM:<>
250 2.1.0 Sender OK
Modern spam attacks frequently use empty senders combined with authenticated sessions to bypass rate limiting systems. Here's a typical attack flow:
EHLO attacker.com
AUTH PLAIN [base64-credentials]
MAIL FROM:<>
RCPT TO:victim@example.com
DATA
From: "Fake CEO"
To: victim@example.com
Subject: Urgent!
...
Most MTAs handle empty senders differently from invalid addresses. For example, in Postfix's main.cf:
# Reject empty MAIL FROM
smtpd_sender_restrictions = reject_empty_sender
But in SmarterMail's case, you need to modify the SMTP server settings to explicitly block empty senders.
For developers building email systems, here's how to validate senders in different languages:
Python Example
def validate_mail_from(address):
if not address or address == "<>":
raise SMTPRejectError(501, "Empty sender not allowed")
# Additional validation logic
C# Example
public void ProcessMailCommand(string mailFrom)
{
if(string.IsNullOrWhiteSpace(mailFrom) || mailFrom == "<>")
{
Session.SendResponse("501 5.1.7 Empty sender prohibited");
return;
}
}
For network-level protection, implement these iptables rules:
# Block empty MAIL FROM in SMTP traffic
iptables -A INPUT -p tcp --dport 25 -m string --string "MAIL FROM:<>" --algo bm -j DROP
Remember that the From:
header is separate from the SMTP envelope sender. A proper defense must check both:
Received-SPF: none (no SPF record for domain of <>)
Authentication-Results: mx.google.com;
spf=neutral (google.com: <> is neither permitted nor denied)
During a recent security audit of a SmarterMail system, we discovered attackers exploiting a fundamental SMTP protocol behavior: sending emails with empty MAIL FROM addresses. The SMTP session log shows:
11:17:06 [xx.xx.xx.xx][15459629] cmd: MAIL FROM:
11:17:07 [xx.xx.xx.xx][15459629] rsp: 250 OK <> Sender ok
This is actually valid according to RFC 5321 (section 4.1.2), which states that reverse-path (MAIL FROM) can be null. Many MTAs, including SurgeMail, accept this as legitimate.
Most email firewalls and rate-limiting systems track messages by the sender address. When MAIL FROM is empty:
- Sender-based rate limiting fails (no address to track)
- SPF checks become meaningless (no domain to validate)
- Reputation systems can't assign sender scores
Here's how a basic SMTP client might implement this in Python:
import smtplib
def send_empty_from_email():
with smtplib.SMTP('mail.example.com', 25) as server:
server.ehlo()
server.starttls()
server.login('hackedaccount@domain.com', 'password')
# The critical empty FROM line
server.mail('')
server.rcpt('victim@target.com')
msg = '''From: Spoofed Name
To: victim@target.com
Subject: Urgent!
This appears to come from appears_in_header@fake.com in headers,
but has no MAIL FROM for tracking.
'''
server.data(msg)
For Postfix administrators, add these to main.cf:
smtpd_sender_restrictions =
reject_null_sender,
reject_unauthenticated_sender_login_mismatch
For Exim, add this ACL rule:
deny senders = :
message = Empty sender address not permitted
The actual exploit relies on the difference between:
- Envelope sender (MAIL FROM in SMTP, empty in this case)
- Header From: (what recipients see in their email client)
This is why you see the sender in headers but not in SMTP logs. Attackers often combine this with compromised accounts to bypass authentication requirements.
Implementing DMARC with a strict policy (p=reject) can help, but requires proper SPF and DKIM configuration. The new Authenticated Received Chain (ARC) protocol helps preserve authentication results across forwarding.