[prev in list] [next in list] [prev in thread] [next in thread] 

List:       oss-security
Subject:    Re: [oss-security] Re: New SMTP smuggling attack
From:       kai <kai () hostland ! ru>
Date:       2023-12-25 18:27:37
Message-ID: 32345105-4692-465c-9a1d-e668c23df18d () hostland ! ru
[Download RAW message or body]

Happy christmas list!

If anyone needs patch for postfix's 3.3.0-1ubuntu0.4 
smtpd_forbid_bare_newline feature it has been attached to this message

On 24/12/2023 12.33, Marcus Meissner wrote:
> On Sat, Dec 23, 2023 at 02:29:34PM +0200, Valtteri Vuorikoski wrote:
>> On Fri, Dec 22, 2023 at 11:46:48AM +0100, Marcus Meissner wrote:
>>> Hi,
>>>
>>> FWIW as no CVEs were to be found yet, I filed a CVE request for Postfix now.
>>>
>>> Not sure if we need it for others like sendmail too, as that is also
>>> referenced by the security researchers.
>> Looks like exim opened a bug on this yesterday too, no sign of CVE yet:
>> <https://bugs.exim.org/show_bug.cgi?id=3063>
> CVEs are assigned now for:
>
> - CVE-2023-51764 postfix
> - CVE-2023-51765 sendmail
> - CVE-2023-51766 exim
>
> Ciao, Marcus
["smtp-smuggling33.patch" (text/x-patch)]

Description: Security
 smtpd_forbid_bare_newline
Author: genie <mail@postfix.org>
Origin: https://www.postfix.org/smtp-smuggling.html
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
Index: postfix-3.3.0/src/global/mail_params.h
===================================================================
--- postfix-3.3.0.orig/src/global/mail_params.h
+++ postfix-3.3.0/src/global/mail_params.h
@@ -4009,6 +4009,15 @@ extern char *var_smtp_dns_re_filter;
 extern char *var_smtpd_dns_re_filter;
 
  /*
+  * Backwards compatibility.
+  */
+#define VAR_SMTPD_FORBID_BARE_LF	"smtpd_forbid_bare_newline"
+#define DEF_SMTPD_FORBID_BARE_LF	0
+
+#define VAR_SMTPD_FORBID_BARE_LF_EXCL	"smtpd_forbid_bare_newline_exclusions"
+#define DEF_SMTPD_FORBID_BARE_LF_EXCL	"$" VAR_MYNETWORKS
+
+ /*
   * Location of shared-library files.
   * 
   * If the files will be installed into a known directory, such as a directory
Index: postfix-3.3.0/src/global/smtp_stream.c
===================================================================
--- postfix-3.3.0.orig/src/global/smtp_stream.c
+++ postfix-3.3.0/src/global/smtp_stream.c
@@ -169,6 +169,8 @@
 
 #include "smtp_stream.h"
 
+int     smtp_forbid_bare_lf;
+
 /* smtp_timeout_reset - reset per-stream error flags, restart deadline timer */
 
 static void smtp_timeout_reset(VSTREAM *stream)
@@ -345,6 +347,9 @@ int     smtp_get(VSTRING *vp, VSTREAM *s
 	 */
     case '\n':
 	vstring_truncate(vp, VSTRING_LEN(vp) - 1);
+        if (smtp_forbid_bare_lf
+            && (VSTRING_LEN(vp) == 0 || vstring_end(vp)[-1] != '\r'))
+            vstream_longjmp(stream, SMTP_ERR_LF);
 	while (VSTRING_LEN(vp) > 0 && vstring_end(vp)[-1] == '\r')
 	    vstring_truncate(vp, VSTRING_LEN(vp) - 1);
 	VSTRING_TERMINATE(vp);
Index: postfix-3.3.0/src/global/smtp_stream.h
===================================================================
--- postfix-3.3.0.orig/src/global/smtp_stream.h
+++ postfix-3.3.0/src/global/smtp_stream.h
@@ -32,6 +32,7 @@
 #define SMTP_ERR_QUIET	3		/* silent cleanup (application) */
 #define SMTP_ERR_NONE	4		/* non-error case */
 #define SMTP_ERR_DATA	5		/* application data error */
+#define SMTP_ERR_LF	6		/* bare <LF> protocol error */
 
 extern void smtp_stream_setup(VSTREAM *, int, int);
 extern void PRINTFLIKE(2, 3) smtp_printf(VSTREAM *, const char *,...);
@@ -41,6 +42,7 @@ extern int smtp_get(VSTRING *, VSTREAM *
 extern void smtp_fputs(const char *, ssize_t len, VSTREAM *);
 extern void smtp_fwrite(const char *, ssize_t len, VSTREAM *);
 extern void smtp_fputc(int, VSTREAM *);
+extern int smtp_forbid_bare_lf;
 
 extern void smtp_vprintf(VSTREAM *, const char *, va_list);
 
Index: postfix-3.3.0/src/smtpd/smtpd.c
===================================================================
--- postfix-3.3.0.orig/src/smtpd/smtpd.c
+++ postfix-3.3.0/src/smtpd/smtpd.c
@@ -1416,6 +1416,10 @@ char   *var_tlsproxy_service;
 char   *var_smtpd_uproxy_proto;
 int     var_smtpd_uproxy_tmout;
 
+bool    var_smtpd_forbid_bare_lf;
+char   *var_smtpd_forbid_bare_lf_excl;
+static NAMADR_LIST *bare_lf_excl;
+
  /*
   * Silly little macros.
   */
@@ -1490,6 +1494,7 @@ static void tls_reset(SMTPD_STATE *);
 #define REASON_TIMEOUT		"timeout"
 #define REASON_LOST_CONNECTION	"lost connection"
 #define REASON_ERROR_LIMIT	"too many errors"
+#define REASON_BARE_LF		"bare <LF> received"
 
 #ifdef USE_TLS
 
@@ -4156,6 +4161,9 @@ static int xclient_cmd(SMTPD_STATE *stat
      */
     xclient_allowed =
 	namadr_list_match(xclient_hosts, state->name, state->addr);
+    smtp_forbid_bare_lf = SMTPD_STAND_ALONE((state)) == 0
+        && var_smtpd_forbid_bare_lf
+        && !namadr_list_match(bare_lf_excl, state->name, state->addr);
     /* NOT: tls_reset() */
     if (got_helo == 0)
 	helo_reset(state);
@@ -4936,6 +4944,13 @@ static void smtpd_proto(SMTPD_STATE *sta
 			     var_myhostname);
 	break;
 
+    case SMTP_ERR_LF:
+        state->reason = REASON_BARE_LF;
+        if (vstream_setjmp(state->client) == 0)
+            smtpd_chat_reply(state, "521 5.5.2 %s Error: bare <LF> received",
+                             var_myhostname);
+        break;
+
     case 0:
 
 	/*
@@ -5461,6 +5476,13 @@ static void smtpd_service(VSTREAM *strea
 	namadr_list_match(xforward_hosts, state.name, state.addr);
 
     /*
+     * Enforce strict SMTP line endings, with compatibility exclusions.
+     */
+    smtp_forbid_bare_lf = SMTPD_STAND_ALONE((&state)) == 0
+        && var_smtpd_forbid_bare_lf
+        && !namadr_list_match(bare_lf_excl, state.name, state.addr);
+
+    /*
      * See if we need to turn on verbose logging for this client.
      */
     debug_peer_check(state.name, state.addr);
@@ -5522,10 +5544,14 @@ static void pre_jail_init(char *unused_n
     hogger_list = namadr_list_init(VAR_SMTPD_HOGGERS, MATCH_FLAG_RETURN
 				   | match_parent_style(VAR_SMTPD_HOGGERS),
 				   var_smtpd_hoggers);
+    bare_lf_excl = namadr_list_init(VAR_SMTPD_FORBID_BARE_LF_EXCL,
+                                    MATCH_FLAG_RETURN
+                                    | match_parent_style(VAR_MYNETWORKS),
+                                    var_smtpd_forbid_bare_lf_excl);
 
     /*
      * Open maps before dropping privileges so we can read passwords etc.
-     * 
+     *
      * XXX We should not do this in stand-alone (sendmail -bs) mode, but we
      * can't use SMTPD_STAND_ALONE(state) here. This means "sendmail -bs"
      * will try to connect to proxymap when invoked by root for mail
@@ -5850,6 +5876,7 @@ int     main(int argc, char **argv)
 	VAR_SMTPD_PEERNAME_LOOKUP, DEF_SMTPD_PEERNAME_LOOKUP, &var_smtpd_peername_lookup,
 	VAR_SMTPD_DELAY_OPEN, DEF_SMTPD_DELAY_OPEN, &var_smtpd_delay_open,
 	VAR_SMTPD_CLIENT_PORT_LOG, DEF_SMTPD_CLIENT_PORT_LOG, &var_smtpd_client_port_log,
+	VAR_SMTPD_FORBID_BARE_LF, DEF_SMTPD_FORBID_BARE_LF, &var_smtpd_forbid_bare_lf,
 	0,
     };
     static const CONFIG_NBOOL_TABLE nbool_table[] = {
@@ -5960,6 +5987,7 @@ int     main(int argc, char **argv)
 	VAR_SMTPD_POLICY_DEF_ACTION, DEF_SMTPD_POLICY_DEF_ACTION, &var_smtpd_policy_def_action, 1, 0,
 	VAR_SMTPD_POLICY_CONTEXT, DEF_SMTPD_POLICY_CONTEXT, &var_smtpd_policy_context, 0, 0,
 	VAR_SMTPD_DNS_RE_FILTER, DEF_SMTPD_DNS_RE_FILTER, &var_smtpd_dns_re_filter, 0, 0,
+	VAR_SMTPD_FORBID_BARE_LF_EXCL, DEF_SMTPD_FORBID_BARE_LF_EXCL, &var_smtpd_forbid_bare_lf_excl, 0, 0,
 	0,
     };
     static const CONFIG_RAW_TABLE raw_table[] = {


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic