From: Maya Dagon (mdagon) Date: Tue, 19 Sep 2023 17:37:22 +0000 (+0000) Subject: Pull request #4003: Smtp: support LF eol, add new alert X-Git-Tag: 3.1.71.0~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0fc0b75ab6f15e565c7bf4c7e343e7a6ca6af315;p=thirdparty%2Fsnort3.git Pull request #4003: Smtp: support LF eol, add new alert Merge in SNORT/snort3 from ~MDAGON/snort3:smtp2 to master Squashed commit of the following: commit bcef85d9d705aee8b9ef431a0afb9c6e2ace0f18 Author: maya dagon Date: Wed Sep 13 16:40:48 2023 -0400 smtp: process DATA\n (no \r) commit 932d3c0f135a352146f67f6e007023c2a1e3bb41 Author: maya dagon Date: Thu Sep 7 18:08:51 2023 -0400 smtp: add alert for mixed LF and CRLF --- diff --git a/doc/reference/builtin_stubs.txt b/doc/reference/builtin_stubs.txt index ec9e52da7..47b2af399 100644 --- a/doc/reference/builtin_stubs.txt +++ b/doc/reference/builtin_stubs.txt @@ -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. diff --git a/src/service_inspectors/smtp/smtp.cc b/src/service_inspectors/smtp/smtp.cc index d548f7ea7..0f7ee27fe 100644 --- a/src/service_inspectors/smtp/smtp.cc +++ b/src/service_inspectors/smtp/smtp.cc @@ -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) { diff --git a/src/service_inspectors/smtp/smtp.h b/src/service_inspectors/smtp/smtp.h index 87aec8156..ff00b92b9 100644 --- a/src/service_inspectors/smtp/smtp.h +++ b/src/service_inspectors/smtp/smtp.h @@ -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 diff --git a/src/service_inspectors/smtp/smtp_module.cc b/src/service_inspectors/smtp/smtp_module.cc index 52b541af6..254c47565 100644 --- a/src/service_inspectors/smtp/smtp_module.cc +++ b/src/service_inspectors/smtp/smtp_module.cc @@ -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 } }; diff --git a/src/service_inspectors/smtp/smtp_module.h b/src/service_inspectors/smtp/smtp_module.h index 17dd3aabc..e9cf062cb 100644 --- a/src/service_inspectors/smtp/smtp_module.h +++ b/src/service_inspectors/smtp/smtp_module.h @@ -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" diff --git a/src/service_inspectors/smtp/smtp_paf.cc b/src/service_inspectors/smtp/smtp_paf.cc index 56a63dfe4..f3b53a150 100644 --- a/src/service_inspectors/smtp/smtp_paf.cc +++ b/src/service_inspectors/smtp/smtp_paf.cc @@ -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); diff --git a/src/service_inspectors/smtp/smtp_util.cc b/src/service_inspectors/smtp/smtp_util.cc index 6917004c6..c3ab17db3 100644 --- a/src/service_inspectors/smtp/smtp_util.cc +++ b/src/service_inspectors/smtp/smtp_util.cc @@ -35,13 +35,14 @@ 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) diff --git a/src/service_inspectors/smtp/smtp_util.h b/src/service_inspectors/smtp/smtp_util.h index b0cda210f..47f5cef79 100644 --- a/src/service_inspectors/smtp/smtp_util.h +++ b/src/service_inspectors/smtp/smtp_util.h @@ -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);