]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #584 in SNORT/snort3 from smtp_auth_overflow to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Wed, 10 Aug 2016 18:24:29 +0000 (14:24 -0400)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Wed, 10 Aug 2016 18:24:29 +0000 (14:24 -0400)
Squashed commit of the following:

commit d0562da0307b36867e78604d8f0065c6b4a5ebb0
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Tue Aug 9 13:51:38 2016 -0400

    SMTP AUTH overflow alert added

    reverting the STARTTLS smtp paf change

    reverting the STARTTLS smtp paf change

    adding snort2lua change for smtp max_auth_command_line_len option

    remove the starttls command processing in SMTP splitter

src/service_inspectors/smtp/smtp.cc
src/service_inspectors/smtp/smtp_config.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_paf.h
tools/snort2lua/preprocessor_states/pps_smtp.cc

index 3cee5f98081926a4f0a5cef387f9f0927d6365d6..0d2ce75966e242d7349967bb04df6ae7079720e4 100644 (file)
@@ -447,6 +447,9 @@ static void SMTP_PrintConfig(SMTP_PROTO_CONF *config)
     else
         LogMessage("%s%d\n", buf, config->max_header_line_len);
 
+    snprintf(buf, sizeof(buf) - 1, "    Max Auth Command Line Length: ");
+    LogMessage("%s%d\n", buf, config->max_auth_command_line_len);
+
     snprintf(buf, sizeof(buf) - 1, "    Max Response Line Length: ");
 
     if (config->max_response_line_len == 0)
@@ -1500,7 +1503,7 @@ public:
     void clear(Packet*) override;
 
     StreamSplitter* get_splitter(bool c2s) override
-    { return new SmtpSplitter(c2s); }
+    { return new SmtpSplitter(c2s, config->max_auth_command_line_len); }
 
     void ProcessSmtpCmdsList(const SmtpCmd*);
 
index f08d92464389b14353b116c744a2894276a0d4e5..4596e18d9c05026bd69bba7d51dfa39a5f313e58 100644 (file)
@@ -123,9 +123,10 @@ struct SMTP_PROTO_CONF
 {
     NORM_TYPES normalize;
     bool ignore_tls_data;
-    int max_command_line_len;
-    int max_header_line_len;
-    int max_response_line_len;
+    int max_auth_command_line_len = 1000;
+    int max_command_line_len = 0;
+    int max_header_line_len = 0;
+    int max_response_line_len = 0;
     int xlink2state;
     MailLogConfig log_config;
     DecodeConfig decode_conf;
index b9d35ba4729f0e309500855677051b9f1cb402c3..4d4bd544876e0a871cd70306ee10ce4242ff13a9 100644 (file)
@@ -46,19 +46,6 @@ SmtpCmd::SmtpCmd(std::string& key, int num)
     }
 }
 
-#define SMTP_COMMAND_OVERFLOW_STR        "Attempted command buffer overflow"
-#define SMTP_DATA_HDR_OVERFLOW_STR       "Attempted data header buffer overflow"
-#define SMTP_RESPONSE_OVERFLOW_STR       "Attempted response buffer overflow"
-#define SMTP_SPECIFIC_CMD_OVERFLOW_STR   "Attempted specific command buffer overflow"
-#define SMTP_UNKNOWN_CMD_STR             "Unknown command"
-#define SMTP_ILLEGAL_CMD_STR             "Illegal command"
-#define SMTP_HEADER_NAME_OVERFLOW_STR    "Attempted header name buffer overflow"
-#define SMTP_XLINK2STATE_OVERFLOW_STR    "Attempted X-Link2State command buffer overflow"
-#define SMTP_B64_DECODING_FAILED_STR     "Base64 Decoding failed."
-#define SMTP_QP_DECODING_FAILED_STR      "Quoted-Printable Decoding failed."
-#define SMTP_UU_DECODING_FAILED_STR      "Unix-to-Unix Decoding failed."
-#define SMTP_AUTH_ABORT_AUTH_STR         "Cyrus SASL authentication attack."
-
 static const Parameter smtp_command_params[] =
 {
     { "command", Parameter::PT_STRING, nullptr, nullptr,
@@ -114,6 +101,9 @@ static const Parameter s_params[] =
     { "log_rcptto", Parameter::PT_BOOL, nullptr, "false",
       "log the recipient's email address extracted from the RCPT TO command" },
 
+    { "max_auth_command_line_len", Parameter::PT_INT, "0:65535", "1000",
+      "max auth command Line Length" },
+
     { "max_command_line_len", Parameter::PT_INT, "0:65535", "0",
       "max Command Line Length" },
 
@@ -146,18 +136,19 @@ static const Parameter s_params[] =
 
 static const RuleMap smtp_rules[] =
 {
-    { SMTP_COMMAND_OVERFLOW, SMTP_COMMAND_OVERFLOW_STR },
-    { SMTP_DATA_HDR_OVERFLOW, SMTP_DATA_HDR_OVERFLOW_STR },
-    { SMTP_RESPONSE_OVERFLOW, SMTP_RESPONSE_OVERFLOW_STR },
-    { SMTP_SPECIFIC_CMD_OVERFLOW, SMTP_SPECIFIC_CMD_OVERFLOW_STR },
-    { SMTP_UNKNOWN_CMD, SMTP_UNKNOWN_CMD_STR },
-    { SMTP_ILLEGAL_CMD, SMTP_ILLEGAL_CMD_STR },
-    { SMTP_HEADER_NAME_OVERFLOW, SMTP_HEADER_NAME_OVERFLOW_STR },
-    { SMTP_XLINK2STATE_OVERFLOW, SMTP_XLINK2STATE_OVERFLOW_STR },
-    { SMTP_B64_DECODING_FAILED, SMTP_B64_DECODING_FAILED_STR },
-    { SMTP_QP_DECODING_FAILED, SMTP_QP_DECODING_FAILED_STR },
-    { SMTP_UU_DECODING_FAILED, SMTP_UU_DECODING_FAILED_STR },
-    { SMTP_AUTH_ABORT_AUTH, SMTP_AUTH_ABORT_AUTH_STR },
+    { SMTP_COMMAND_OVERFLOW, "Attempted command buffer overflow" },
+    { SMTP_DATA_HDR_OVERFLOW, "Attempted data header buffer overflow" },
+    { SMTP_RESPONSE_OVERFLOW, "Attempted response buffer overflow" },
+    { SMTP_SPECIFIC_CMD_OVERFLOW, "Attempted specific command buffer overflow" },
+    { SMTP_UNKNOWN_CMD, "Unknown command" },
+    { SMTP_ILLEGAL_CMD, "Illegal command" },
+    { SMTP_HEADER_NAME_OVERFLOW, "Attempted header name buffer overflow" },
+    { SMTP_XLINK2STATE_OVERFLOW, "Attempted X-Link2State command buffer overflow" },
+    { SMTP_B64_DECODING_FAILED, "Base64 Decoding failed" },
+    { SMTP_QP_DECODING_FAILED, "Quoted-Printable Decoding failed" },
+    { SMTP_UU_DECODING_FAILED, "Unix-to-Unix Decoding failed" },
+    { SMTP_AUTH_ABORT_AUTH, "Cyrus SASL authentication attack" },
+    { SMTP_AUTH_COMMAND_OVERFLOW, "Attempted authentication command buffer overflow" },
 
     { 0, nullptr }
 };
@@ -284,6 +275,9 @@ bool SmtpModule::set(const char*, Value& v, SnortConfig*)
     else if ( v.is("log_email_hdrs"))
         config->log_config.log_email_hdrs = v.get_bool();
 
+    else if ( v.is("max_auth_command_line_len") )
+        config->max_auth_command_line_len = v.get_long();
+
     else if ( v.is("max_command_line_len") )
         config->max_command_line_len = v.get_long();
 
@@ -332,9 +326,6 @@ bool SmtpModule::begin(const char*, int, SnortConfig*)
     if(!config)
     {
         config = new SMTP_PROTO_CONF;
-        config->max_header_line_len = 0;
-        config->max_response_line_len = 0;
-        config->max_command_line_len = 0;
         config->xlink2state = ALERT_XLINK2STATE;
         config->decode_conf.set_ignore_data(config->ignore_tls_data = false);
         config->normalize = NORMALIZE_NONE;
index fa53db8c0da0b9f422a4ae66df2afb9cf2f7de1d..ebe998cb0f6dec5b860ffdf4ea443b2d3f69fb8d 100644 (file)
@@ -45,6 +45,7 @@
 //#define SMTP_BITENC_DECODING_FAILED 12
 #define SMTP_UU_DECODING_FAILED     13
 #define SMTP_AUTH_ABORT_AUTH        14
+#define SMTP_AUTH_COMMAND_OVERFLOW  15
 
 #define SMTP_NAME "smtp"
 #define SMTP_HELP "smtp inspection"
index ecaa1d707e599596cd1e5bb684500dc6a50fc1e7..7d1902b61cb995bbefa57702c05608858976fedf 100644 (file)
 
 #include "main/snort_types.h"
 #include "main/snort_debug.h"
+#include "events/event_queue.h"
 
 #include "smtp.h"
+#include "smtp_module.h"
 
 /* State tracker for MIME PAF */
 enum SmtpDataCMD
 {
+    SMTP_PAF_AUTH_CMD,
     SMTP_PAF_BDAT_CMD,
     SMTP_PAF_DATA_CMD,
-    SMTP_PAF_XEXCH50_CMD,
-    SMTP_PAF_STRARTTLS_CMD
+    SMTP_PAF_XEXCH50_CMD
 };
 
 struct SmtpPAFToken
@@ -44,10 +46,10 @@ struct SmtpPAFToken
 
 const SmtpPAFToken smtp_paf_tokens[] =
 {
+    { "AUTH",         4, SMTP_PAF_AUTH_CMD, false },
     { "BDAT",         4, SMTP_PAF_BDAT_CMD, true },
     { "DATA",         4, SMTP_PAF_DATA_CMD, true },
     { "XEXCH50",      7, SMTP_PAF_XEXCH50_CMD, true },
-    { "STRARTTLS",    9, SMTP_PAF_STRARTTLS_CMD, false },
     { NULL,           0, 0, false }
 };
 
@@ -101,6 +103,11 @@ static inline char* init_cmd_search(SmtpCmdSearchInfo* search_info,  uint8_t ch)
     /* Use the first byte to choose data command)*/
     switch (ch)
     {
+    case 'a':
+    case 'A':
+        search_info->search_state = &smtp_paf_tokens[SMTP_PAF_AUTH_CMD].name[1];
+        search_info->search_id = SMTP_PAF_AUTH_CMD;
+        break;
     case 'b':
     case 'B':
         search_info->search_state = &smtp_paf_tokens[SMTP_PAF_BDAT_CMD].name[1];
@@ -116,11 +123,6 @@ static inline char* init_cmd_search(SmtpCmdSearchInfo* search_info,  uint8_t ch)
         search_info->search_state = &smtp_paf_tokens[SMTP_PAF_XEXCH50_CMD].name[1];
         search_info->search_id = SMTP_PAF_XEXCH50_CMD;
         break;
-    case 's':
-    case 'S':
-        search_info->search_state = &smtp_paf_tokens[SMTP_PAF_STRARTTLS_CMD].name[1];
-        search_info->search_id = SMTP_PAF_STRARTTLS_CMD;
-        break;
     default:
         search_info->search_state = NULL;
         break;
@@ -190,7 +192,7 @@ static SmtpPafDataLenStatus get_length(char c, uint32_t* len)
     return SMTP_PAF_LENGTH_CONTINUE;
 }
 
-/* Currently, we support "BDAT", "DATA", "XEXCH50", "STRARTTLS"
+/* Currently, we support "BDAT", "DATA", "XEXCH50", "AUTH"
  *  * Each data command should start from offset 0,
  *   * since previous data have been flushed
  *    */
@@ -278,10 +280,11 @@ static inline bool process_data(SmtpPafData* pfdata,  uint8_t data)
  *   * For data, flush at boundary
  *    */
 static inline StreamSplitter::Status smtp_paf_client(SmtpPafData* pfdata,
-    const uint8_t* data, uint32_t len, uint32_t* fp)
+    const uint8_t* data, uint32_t len, uint32_t* fp, int max_auth_command_line_len)
 {
     uint32_t i;
     uint32_t boundary_start = 0;
+    bool alert_generated = false;
 
     DebugFormat(DEBUG_SMTP, "From client: %s \n", data);
     for (i = 0; i < len; i++)
@@ -298,7 +301,25 @@ static inline StreamSplitter::Status smtp_paf_client(SmtpPafData* pfdata,
             }
             break;
         case SMTP_PAF_DATA_STATE:
-            if (process_data(pfdata, ch))
+            if (pfdata->cmd_info.search_id == SMTP_PAF_AUTH_CMD)
+            {
+                if ( max_auth_command_line_len && 
+                        (((int)i + pfdata->data_info.boundary_len) > max_auth_command_line_len) &&
+                        !alert_generated)
+                {
+                    SnortEventqAdd(GID_SMTP, SMTP_AUTH_COMMAND_OVERFLOW);
+                    alert_generated = true;
+                }
+                if (ch == '\n')
+                {
+                    pfdata->smtp_state = SMTP_PAF_CMD_STATE;
+                    pfdata->end_of_data = true;
+                    reset_data_states(pfdata);
+                }
+                if ( (i == len-1) && (pfdata->smtp_state != SMTP_PAF_CMD_STATE) )
+                    pfdata->data_info.boundary_len += len;
+            }
+            else if (process_data(pfdata, ch))
             {
                 DebugMessage(DEBUG_SMTP, "Flush data!\n");
                 *fp = i + 1;
@@ -323,10 +344,11 @@ static inline StreamSplitter::Status smtp_paf_client(SmtpPafData* pfdata,
 // callback for stateful scanning of in-order raw payload
 //--------------------------------------------------------------------
 
-SmtpSplitter::SmtpSplitter(bool c2s) : StreamSplitter(c2s)
+SmtpSplitter::SmtpSplitter(bool c2s, int len) : StreamSplitter(c2s)
 {
     memset(&state, 0, sizeof(state));
     reset_data_states(&state);
+    max_auth_command_line_len = len;
 }
 
 SmtpSplitter::~SmtpSplitter() { }
@@ -365,7 +387,7 @@ StreamSplitter::Status SmtpSplitter::scan(
     else
     {
         DebugMessage(DEBUG_SMTP, "PAF: From client.\n");
-        return smtp_paf_client(pfdata, data, len, fp);
+        return smtp_paf_client(pfdata, data, len, fp, max_auth_command_line_len);
     }
 }
 
index 74824fdbae23c335714146012c34d4a9f13a692c..5ec6dc58f1451e65e0a0238e066288fcf79d95b9 100644 (file)
@@ -65,7 +65,7 @@ struct SmtpPafData
 class SmtpSplitter : public StreamSplitter
 {
 public:
-    SmtpSplitter(bool c2s);
+    SmtpSplitter(bool c2s, int max_auth_cmd_line_len);
     ~SmtpSplitter();
 
     Status scan(Flow*, const uint8_t* data, uint32_t len,
@@ -75,6 +75,9 @@ public:
 
 public:
     SmtpPafData state;
+
+private:
+    int max_auth_command_line_len;
 };
 
 // Function: Check if IMAP data end is reached
index 04161fe5b7253724873b71b6822274d0585859d5..bf3e9a8ca5552921adc78afed6924728433ea689 100644 (file)
@@ -214,6 +214,10 @@ bool Smtp::convert(std::istringstream& data_stream)
         {
             tmpval = parse_int_option("email_hdrs_log_depth", data_stream, false);
         }
+        else if (!keyword.compare("max_auth_command_line_len"))
+        {
+            tmpval = parse_int_option("max_auth_command_line_len", data_stream, false);
+        }
         else if (!keyword.compare("max_command_line_len"))
         {
             tmpval = parse_int_option("max_command_line_len", data_stream, false);