SMTP Smuggling
[An updated version of this text may be found at https://www.postfix.org/smtp-smuggling.html]
Author: Wietse Venema
Last update: January 22, 2024
Summary
Days before a 10+ day Christmas holiday break and associated production change freeze, SEC Consult has published an email spoofing attack that involves a composition of email services with specific differences in the way they handle line endings other than <CR><LF>.
Technically, the attack exploits END-OF-DATA confusion in a receiving mail service, by tricking a sending mail service to send a non-standard END-OF-DATA sequence <LF>.<LF> or <LF>.<CR><LF> in the middle of an email messsage, followed by the attacker's SMTP commands that inject a spoofed email message (the standard END-OF-DATA sequence is <CR><LF>.<CR><LF>).
The vulnerability was introduced many decades ago in Sendmail, by allowing the non-standard <LF> line ending in addition to the standard <CR><LF>. For compatibility with programs that expect Sendmail behavior, the non-standard <LF> line ending was also allowed by other SMTP servers including Postfix and Exim.
Unfortunately, criticial information provided by the researcher was not passed on to Postfix maintainers before publication of the attack, otherwise we would certainly have convinced SEC Consult to postpone publication until after people had a chance to update their Postfix or other affected systems.
The net result: a presumably unintended zero-day attack was published because some people weren't aware of the scope of the attack.
After the attack was published, CVEs were assigned for Postfix, Sendmail, and Exim (see cve.mitre.org for a full list of affected MTAs).
Details
The attack involves a COMPOSITION of two email services with specific differences in the way they handle non-standard forms of the SMTP End-of-DATA sequence:
-
One originating email service A that receives an email message from an authenticated attacker, containing a non-standard SMTP End-of-DATA sequence such as <LF>.<CR><LF>, and that propagates that non-standard End-of-DATA sequence verbatim when it forwards that message to:
-
One destination email service B that interprets a non-standard End-of-DATA sequence such as <LF>.<CR><LF> as if it received the standard sequence <CR><LF>.<CR><LF>. When this is followed by "smuggled" SMTP MAIL/RCPT/DATA or MAIL/RCPT/BDAT commands and message header plus body text, email service B is tricked into receiving two email messages: one message with the content before the non-standard End-of-DATA sequence, and one message with the "smuggled" header plus body text after the "smuggled" SMTP commands. All this when email service A sends only one message.
Postfix is an example of email service B. Microsoft's outlook.com was an example of email service A.
Impact
-
The authenticated attacker can use the "smuggled" SMTP MAIL/RCPT/DATA or MAIL/RCPT/BDAT commands and header plus body text, to spoof an email message from any MAIL FROM address whose domain is hosted at originating email service A, to any RCPT TO address whose domain is hosted at destination email service B.
-
The spoofed email message will pass SPF-based DMARC checks at email service B, because the spoofed message has a MAIL FROM address whose domain is hosted at email service A, and because the message was received from an IP address that belongs to email service A.
Short-term workarounds
A short-term workaround can be deployed now, before the upcoming long holiday and associated production change freeze.
The idea is to reject unauthorised SMTP command pipelining (one network packet contains multiple lines with smuggled SMTP commands and message content), and to reject BDAT commands. That will stop many forms of the published attack (BDAT is part of the CHUNKING extension; it allows command pipelining that isn't allowed with the DATA command).
NOTE: this will block misuse of SMTP command pipelining. It will not block message pipelining (multiple MAIL transactions per session), nor will it block a malformed end of line. Malformed line endings are addressed with the long-term solution.
-
With all Postfix versions:
main.cf: smtpd_data_restrictions = reject_unauth_pipelining smtpd_discard_ehlo_keywords = chunking, silent-discard
-
Postfix 3.9, 3.8.1, 3.7.6, 3.6.10 and 3.5.20 can also block the same forms of the published attack with:
main.cf: smtpd_forbid_unauth_pipelining = yes smtpd_discard_ehlo_keywords = chunking, silent-discard
With Postfix 3.8.1, 3.7.6, 3.6.10 and 3.5.20, smtpd_forbid_unauth_pipelining is disabled by default for backwards compatibility.
With Postfix 3.9 (stable release expected early 2024), smtpd_forbid_unauth_pipelining is enabled by default, but it is still prudent to disable "chunking" as shown above.
Compatibility: the setting "smtpd_forbid_unauth_pipelining = yes" or "smtpd_data_restrictions = reject_unauth_pipelining" may break legitimate SMTP clients that mis-implement SMTP, but such clients are exceedingly rare, especially when email is sent across the Internet.
Long-term fix
An updated long-term fix is available for Postfix 3.8.5, 3.7.10, 3.6.14 and 3.5.24. This stops all forms of the smuggling attacks on recipients at a Postfix server. It introduces a new optional feature that is disabled by default on Postfix versions < 3.9.
Sites concerned about SMTP smuggling attacks should enable this feature on Internet-facing Postfix servers. For compatibility with non-standard clients, Postfix by default excludes clients in mynetworks from this countermeasure.
An older long-term fix recommended using "smtpd_forbid_bare_newline = yes". Use that if you have Postfix 3.8.4, 3.7.9, 3.6.13 or 3.5.23. That setting still protects later Postfix versions against SMTP smuggling.
The recommended settings are:
main.cf: # Require the standard End-of-DATA sequence <CR><LF>.<CR><LF>. # Otherwise, allow bare <LF> and process it as if the client sent # <CR><LF>. # # This maintains compatibility with many legitimate SMTP client # applications that send a mix of standard and non-standard line # endings, but will fail to receive email from client implementations # that do not terminate DATA content with the standard End-of-DATA # sequence <CR><LF>.<CR><LF>. # # Such clients can be allowlisted with smtpd_forbid_bare_newline_exclusions. # The example below allowlists SMTP clients in trusted networks. # smtpd_forbid_bare_newline = normalize smtpd_forbid_bare_newline_exclusions = $mynetworks
Notes:
-
The older setting "smtpd_forbid_bare_newline = yes" is now an alias for "smtpd_forbid_bare_newline = normalize".
-
To reject commands or messages with a bare <LF> use the new setting "smtpd_forbid_bare_newline = reject". This is more likely to reject legitimate email than "normalize".
Fixes for older Postfix versions
First, the " Short-term workaround " will prevent all realistic smuggling scenarios, even if some audit tool claims otherwise.
That said, patches for no longer supported Postfix releases are available from the source code mirrors listed at the Postfix download webpage. See the "Smuggling patches for older releases" link at the top of a "Postfix Source Code" page.
Reach out to Wietse if you need to patch an older version.
False claims from test tools
Some test tools may make false vulnerability claims based on non-viable attack patterns. This topic is covered in a separate document.
Timeline
-
Dec 18 Found out that SEC Consult has published an attack that involves the composition of two different email service behaviors with non-standard line endings in SMTP.
-
Dec 19 Research and implement a fix for Postfix, start testing and Q/A.
-
Dec 20 Draft this response document at https://www.postfix.org/smtp-smuggling.html.
-
Dec 21 Address two problems found during validation (with BDAT and XCLIENT), update the Postfix 3.9 unstable release, and start patching the Postfix 3.5 .. 3.8 stable versions.
-
Dec 22: Publish updated source code releases for stable Postfix versions 3.8.4, 3.7.9, 3.6.13, 3.5.23.
-
Dec 22: Last day before a 10+ day holiday break, start of production change freezes until early January.
-
OSS distributions publish updated packages for stable Postfix versions 3.8.4, 3.7.9, 3.6.13, 3.5.23.
-
Jan 8: Add link to false-smuggling-claims.html.
-
Jan 21: Publish updated stable Postfix versions 3.8.5, 3.7.10, 3.6.14 and 3.5.24, with the option to prevent SMTP smuggling without rejecting bare <LF>.
-
Jan 21: Start publishing patches for older Postfix versions that are no longer supported.