]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #4003: Smtp: support LF eol, add new alert
authorMaya Dagon (mdagon) <mdagon@cisco.com>
Tue, 19 Sep 2023 17:37:22 +0000 (17:37 +0000)
committerOleksii Shumeiko -X (oshumeik - SOFTSERVE INC at Cisco) <oshumeik@cisco.com>
Tue, 19 Sep 2023 17:37:22 +0000 (17:37 +0000)
Merge in SNORT/snort3 from ~MDAGON/snort3:smtp2 to master

Squashed commit of the following:

commit bcef85d9d705aee8b9ef431a0afb9c6e2ace0f18
Author: maya dagon <mdagon@cisco.com>
Date:   Wed Sep 13 16:40:48 2023 -0400

    smtp: process DATA\n (no \r)

commit 932d3c0f135a352146f67f6e007023c2a1e3bb41
Author: maya dagon <mdagon@cisco.com>
Date:   Thu Sep 7 18:08:51 2023 -0400

    smtp: add alert for mixed LF and CRLF

doc/reference/builtin_stubs.txt
src/service_inspectors/smtp/smtp.cc
src/service_inspectors/smtp/smtp.h
src/service_inspectors/smtp/smtp_module.cc
src/service_inspectors/smtp/smtp_module.h
src/service_inspectors/smtp/smtp_paf.cc
src/service_inspectors/smtp/smtp_util.cc
src/service_inspectors/smtp/smtp_util.h

index ec9e52da79b45caba24fcdd11b519677abc8d878..47b2af399694b6ca28ea7dc0888a6d90638953e4 100644 (file)
@@ -1715,6 +1715,10 @@ File decompression failed.
 
 SMTP STARTTLS command injection attempt.
 
+124:18
+
+SMTP traffic has a mix of LF and CRLF as end of line
+
 125:1
 
 TELNET command is detected on FTP control channel.
index d548f7ea7f0f1aca095d94d07e573abb7b67dd89..0f7ee27feeff5c79c04d823f959ab12100a39cb7 100644 (file)
@@ -200,6 +200,7 @@ enum SMTPCmdGroup
 
 static void snort_smtp(SmtpProtoConf* GlobalConf, Packet* p);
 static void SMTP_ResetState(Flow*);
+static void update_eol_state(SMTPEol new_eol, SMTPEol& curr_eol_state);
 
 SmtpFlowData::SmtpFlowData() : FlowData(inspector_id)
 {
@@ -696,7 +697,7 @@ static const uint8_t* SMTP_HandleCommand(SmtpProtoConf* config, Packet* p, SMTPD
     char alert_long_command_line = 0;
 
     /* get end of line and end of line marker */
-    SMTP_GetEOL(ptr, end, &eol, &eolm);
+    SMTPEol new_eol = SMTP_GetEOL(ptr, end, &eol, &eolm);
 
     /* calculate length of command line */
     cmd_line_len = eol - ptr;
@@ -1020,6 +1021,8 @@ static const uint8_t* SMTP_HandleCommand(SmtpProtoConf* config, Packet* p, SMTPD
        DetectionEngine::queue_event(GID_SMTP, SMTP_STARTTLS_INJECTION_ATTEMPT);
     }
 
+    update_eol_state(new_eol, smtp_ssn->client_eol);
+
     return eol;
 }
 
@@ -1131,7 +1134,7 @@ static void SMTP_ProcessServerPacket(
         const uint8_t* eol;
         const uint8_t* eolm;
 
-        SMTP_GetEOL(ptr, end, &eol, &eolm);
+        SMTPEol new_eol = SMTP_GetEOL(ptr, end, &eol, &eolm);
 
         int resp_line_len = eol - ptr;
 
@@ -1212,10 +1215,11 @@ static void SMTP_ProcessServerPacket(
             }
         }
 
-        if ((config->max_response_line_len != 0) &&
-            (resp_line_len > config->max_response_line_len) &&
-            (smtp_ssn->state != STATE_TLS_DATA))
+        if (smtp_ssn->state != STATE_TLS_DATA)
         {
+            update_eol_state(new_eol, smtp_ssn->server_eol);
+            if ((config->max_response_line_len != 0) &&
+                (resp_line_len > config->max_response_line_len))
             DetectionEngine::queue_event(GID_SMTP, SMTP_RESPONSE_OVERFLOW);
         }
 
@@ -1383,6 +1387,25 @@ static void SMTP_RegXtraDataFuncs(SmtpProtoConf* config)
     config->xtra_ehdrs_id = Stream::reg_xtra_data_cb(SMTP_GetEmailHdrs);
 }
 
+static void update_eol_state(SMTPEol new_eol, SMTPEol& curr_eol_state)
+{
+    if (new_eol == EOL_NOT_SEEN or curr_eol_state == EOL_MIXED)
+        return;
+
+    if (curr_eol_state == EOL_NOT_SEEN)
+    {
+        curr_eol_state = new_eol;
+        return;
+    }
+
+    if ((new_eol == EOL_LF and curr_eol_state == EOL_CRLF) or
+        (new_eol == EOL_CRLF and curr_eol_state == EOL_LF))
+    {
+        curr_eol_state = EOL_MIXED;
+        DetectionEngine::queue_event(GID_SMTP, SMTP_LF_CRLF_MIX);
+    }
+}
+
 int SmtpMime::handle_header_line(
     const uint8_t* ptr, const uint8_t* eol, int max_header_len, Packet* p)
 {
index 87aec8156c73b226d20080dc33dca9212d0c90ad..ff00b92b9026483db02e070e1a972fc2abb33a40 100644 (file)
@@ -123,6 +123,14 @@ enum SMTPDataEndEnum
     DATA_END_LAST
 };
 
+enum SMTPEol
+{
+    EOL_NOT_SEEN,
+    EOL_LF,
+    EOL_CRLF,
+    EOL_MIXED
+};
+
 struct SMTPSearchInfo
 {
     int id;
@@ -173,7 +181,9 @@ struct SMTPData
                  auth_name{nullptr},
                  client_requested_starttls{false},
                  pipelined_command_counter{0},
-                 server_accepted_starttls{false}
+                 server_accepted_starttls{false},
+                 client_eol{EOL_NOT_SEEN},
+                 server_eol{EOL_NOT_SEEN}
     { }
 
     int state;
@@ -186,6 +196,8 @@ struct SMTPData
     bool client_requested_starttls;
     size_t pipelined_command_counter;
     bool server_accepted_starttls;
+    SMTPEol client_eol;
+    SMTPEol server_eol;
 };
 
 class SmtpFlowData : public snort::FlowData
index 52b541af637023066afaea683e468af2ca640d0d..254c47565fb8405b03ac1cba3cfa534cd08c759c 100644 (file)
@@ -171,7 +171,7 @@ static const RuleMap smtp_rules[] =
     { SMTP_AUTH_COMMAND_OVERFLOW, "attempted authentication command buffer overflow" },
     { SMTP_FILE_DECOMP_FAILED, "file decompression failed" },
     { SMTP_STARTTLS_INJECTION_ATTEMPT, "STARTTLS command injection attempt"},
-
+    { SMTP_LF_CRLF_MIX, "mix of LF and CRLF as end of line" },
 
     { 0, nullptr }
 };
index 17dd3aabc6d005180c7c50b042d135c3e950cb0f..e9cf062cb7953f402c720a907095fbf4364c947b 100644 (file)
@@ -46,6 +46,7 @@
 #define SMTP_AUTH_COMMAND_OVERFLOW  15
 #define SMTP_FILE_DECOMP_FAILED     16
 #define SMTP_STARTTLS_INJECTION_ATTEMPT 17
+#define SMTP_LF_CRLF_MIX            18
 
 #define SMTP_NAME "smtp"
 #define SMTP_HELP "smtp inspection"
index 56a63dfe48877f1a0a41b4ec3ef029036ae7207b..f3b53a150e04061a4e35cdf0d583bb9a10af449b 100644 (file)
@@ -204,7 +204,9 @@ static inline bool process_command(SmtpPafData* pfdata,  uint8_t val)
     /*State unknown, start cmd search start from EOL, flush on EOL*/
     if (val == '\n')
     {
-        if (pfdata->cmd_info.cmd_state == SMTP_PAF_CMD_DATA_END_STATE)
+        if ((pfdata->cmd_info.cmd_state == SMTP_PAF_CMD_DATA_END_STATE) or
+            ((pfdata->cmd_info.cmd_state == SMTP_PAF_CMD_DATA_LENGTH_STATE) and
+            (pfdata->cmd_info.search_id == SMTP_PAF_DATA_CMD)))
         {
             pfdata->smtp_state = SMTP_PAF_DATA_STATE;
             reset_data_states(pfdata);
index 6917004c68f665c2fd357c4189270892628be9d9..c3ab17db37b475f0c5a31f4af38b1f199f968c0e 100644 (file)
 
 using namespace snort;
 
-void SMTP_GetEOL(const uint8_t* ptr, const uint8_t* end,
+SMTPEol SMTP_GetEOL(const uint8_t* ptr, const uint8_t* end,
     const uint8_t** eol, const uint8_t** eolm)
 {
     assert(ptr and end and eol and eolm);
 
     const uint8_t* tmp_eolm;
     const uint8_t* tmp_eol = (const uint8_t*)memchr(ptr, '\n', end - ptr);
+    SMTPEol eol_state = EOL_NOT_SEEN;
 
     if (tmp_eol == nullptr)
     {
@@ -55,10 +56,12 @@ void SMTP_GetEOL(const uint8_t* ptr, const uint8_t* end,
         if ((tmp_eol > ptr) && (*(tmp_eol - 1) == '\r'))
         {
             tmp_eolm = tmp_eol - 1;
+            eol_state = EOL_CRLF;
         }
         else
         {
             tmp_eolm = tmp_eol;
+            eol_state = EOL_LF;
         }
 
         /* move past newline */
@@ -67,6 +70,7 @@ void SMTP_GetEOL(const uint8_t* ptr, const uint8_t* end,
 
     *eol = tmp_eol;
     *eolm = tmp_eolm;
+    return eol_state;
 }
 
 void SMTP_ResetAltBuffer(Packet* p)
index b0cda210ff23f7957082ee1b121a55b6325089ee..47f5cef797e09e0c647cab18a29796bcbcbd49c4 100644 (file)
@@ -24,6 +24,7 @@
 
 // SMTP helper functions
 
+#include "smtp.h"
 #include "smtp_config.h"
 
 namespace snort
@@ -31,7 +32,7 @@ namespace snort
 struct Packet;
 }
 
-void SMTP_GetEOL(const uint8_t*, const uint8_t*, const uint8_t**, const uint8_t**);
+SMTPEol SMTP_GetEOL(const uint8_t*, const uint8_t*, const uint8_t**, const uint8_t**);
 void SMTP_LogFuncs(SmtpProtoConf*, snort::Packet*, snort::MimeSession*);
 
 int SMTP_CopyToAltBuffer(snort::Packet*, const uint8_t*, int);