Defending Against SMTP Smuggling with KumoMTA

  • December 20, 2023

What is SMTP Smuggling?

On September 18th there was a new exploit published regarding SMTP Smuggling, which you can read about at https://sec-consult.com/blog/detail/smtp-smuggling-spoofing-e-mails-worldwide/.

The short version is that an attacker can potentially exploit a situation where a sending MTA is tricked into sending <lf>.<lf> as part of the message data, and then relaying that to a receiving MTA that incorrectly interprets that sequence as the end of the message. If the attacker embeds SMTP protocol commands in such a message there is a chance that they will be interpreted as authorized commands by the receiving MTA and may result in additional messages being sent on behalf of the sending MTA, but without its knowledge or express permission.

This is different from an attacker directly connecting to the receiving MTA to spoof the messages; because in this situation the messages are coming from the sending MTA they will SPF align and, if the connection is using other authentication mechanisms, they will likely also be considered authenticated in the same way. This makes it potentially possible for the attacker to spoof the same or other domains for which the sending MTA is authorized to send, which is a serious threat if the sending MTA is at a major ESP.


            Figure 15: SMTP smuggling from admin@gmx.net to user@provider.example

In the example above, if the sending MTA doesn't consider the non-conformant \n.\r\n sequence as the end of the message data, but the receiving MTA does, then the receiving MTA will see two messages coming from the sending MTA and potentially accept both since the incoming session is SPF-aligned.

SMTP Smuggling is a configuration issue, relying on differing, relaxed conformance, configurations on two MTAs, rather than an inherent flaw in SMTP itself. RFC 5321 explicitly forbids the transition of a single <cr> or <lf> character:

In addition, the appearance of "bare" "CR" or "LF" characters in text (i.e., either without the other) has a long history of causing problems in mail implementations and applications that use the mail system as a tool. SMTP client implementations MUST NOT transmit these characters except when they are intended as line terminators and then MUST, as indicated above, transmit them only as a <CRLF> sequence.

Defending against SMTP Smuggling in KumoMTA

KumoMTA allows you to choose how to handle this kind of input:

  1. 1) You can ignore it and allow it to relay (not recommended)
  2. 2) You can check and reject it (recommended)
  3. 3) You can accept and fix the non-conforming line endings to <cr><lf>. If you are interfacing with a legacy system, this might be the option for you.

Here's an example that shows how to check and reject this kind of message:

-- Processing of incoming messages via SMTP
kumo.on('smtp_server_message_received', function(msg)
  -- Protect against SMTP Smuggling (https://sec-consult.com/blog/detail/smtp-smuggling-spoofing-e-mails-worldwide/)
  local failed = msg:check_fix_conformance(
    -- check for and reject messages with these issues:
    'NON_CANONICAL_LINE_ENDINGS',
    -- fix messages with these issues:
    ''
  )
  if failed then
    kumo.reject(552, string.format('5.6.0 %s', failed))
  end
  -- Call the queue helper to set up the queue for the message.
  queue_helper:apply(msg)
  -- SIGNING MUST COME LAST OR YOU COULD BREAK YOUR DKIM SIGNATURES
  dkim_signer(msg)
end)

To help protect all our users, we have added this check to the example configuration that we encourage all users to use as their starting point for their installations. For those that would prefer to fix line endings rather than reject the messages, they can move the NON_CANONICAL_LINE_ENDINGS element from the first argument in check_fix_conformance to the second (from "check" to "fix").