From: Andres Avila Segura (aavilase) Date: Fri, 13 Dec 2024 20:01:54 +0000 (+0000) Subject: Pull request #4517: pop: adding wrong bytes threshold to determine if pop splitter... X-Git-Tag: 3.6.1.0~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b661c2a20a26698e5e338660f2f8b477a89b882a;p=thirdparty%2Fsnort3.git Pull request #4517: pop: adding wrong bytes threshold to determine if pop splitter should fallback Merge in SNORT/snort3 from ~AAVILASE/snort3:pop_inspector_fallback_functionality to master Squashed commit of the following: commit 38022a1ce200493ee3f61d72674c505c4f0b4687 Author: Andres Avila Date: Thu Nov 7 11:51:21 2024 -0500 pop: adding wrong bytes threshold to determine if pop splitter should fallback --- diff --git a/src/service_inspectors/pop/pop_paf.cc b/src/service_inspectors/pop/pop_paf.cc index ebffc3767..6427e37e3 100644 --- a/src/service_inspectors/pop/pop_paf.cc +++ b/src/service_inspectors/pop/pop_paf.cc @@ -67,7 +67,7 @@ static bool search_for_command(PopPafData* pfdata, const uint8_t ch) } else { - pfdata->cmd_state.status = POP_CMD_FIN; + pfdata->cmd_state.status = POP_CMD_INVALID; } return false; @@ -87,6 +87,21 @@ static bool init_command_search(PopPafData* pfdata, const uint8_t ch) pfdata->cmd_state.exp_resp = POP_PAF_MULTI_LINE_STATE; pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_CAPA].name[1]); break; + case 'a': + case 'A': + pfdata->cmd_state.exp_resp = POP_PAF_SINGLE_LINE_STATE; + pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_APOP].name[1]); + break; + case 'd': + case 'D': + pfdata->cmd_state.exp_resp = POP_PAF_SINGLE_LINE_STATE; + pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_DELE].name[1]); + break; + case 'p': + case 'P': + pfdata->cmd_state.exp_resp = POP_PAF_SINGLE_LINE_STATE; + pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_PASS].name[1]); + break; case 'l': case 'L': pfdata->cmd_state.exp_resp = POP_PAF_HAS_ARG; @@ -107,8 +122,23 @@ static bool init_command_search(PopPafData* pfdata, const uint8_t ch) pfdata->cmd_state.exp_resp = POP_PAF_HAS_ARG; pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_UIDL].name[1]); break; + case 'n': + case 'N': + pfdata->cmd_state.exp_resp = POP_PAF_SINGLE_LINE_STATE; + pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_NOOP].name[1]); + break; + case 'q': + case 'Q': + pfdata->cmd_state.exp_resp = POP_PAF_SINGLE_LINE_STATE; + pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_QUIT].name[1]); + break; + case 's': + case 'S': + pfdata->cmd_state.exp_resp = POP_PAF_SINGLE_LINE_STATE; + pfdata->cmd_state.next_letter = &(pop_known_cmds[CMD_STAT].name[1]); + break; default: - pfdata->cmd_state.status = POP_CMD_FIN; + pfdata->cmd_state.status = POP_CMD_INVALID; } return false; @@ -153,12 +183,21 @@ static inline void reset_data_states(PopPafData* pfdata) * -ERR. * * RETURNS: - * true - if the character is a + + * true - if the character is a + or - * false - if the character is anything else */ -static inline int valid_response(const uint8_t data) +static inline bool valid_response(PopPafData* pfdata, const uint8_t data) { - return (data == '+'); + if (data == '+') + { + return true; + } else if (data == '-') + { + //-ERR is always single line + pfdata->pop_state = POP_PAF_SINGLE_LINE_STATE; + return true; + } + return false; } /* @@ -256,8 +295,20 @@ static StreamSplitter::Status pop_paf_server(PopPafData* pfdata, uint32_t boundary_start = 0; // if a negative response was received, it will be a one line response. - if (!pfdata->cmd_continued && !valid_response(*data)) - pfdata->pop_state = POP_PAF_SINGLE_LINE_STATE; + if (!pfdata->cmd_continued && !valid_response(pfdata, *data)) + { + pfdata->server_bytes_seen += len; + if (pfdata->server_bytes_seen > POP_MAX_OCTETS) + { + pfdata->server_bytes_seen = 0; + reset_data_states(pfdata); + return StreamSplitter::ABORT; + } + } + else + { + pfdata->server_bytes_seen = 0; + } for (i = 0; i < len; i++) { @@ -336,14 +387,30 @@ static StreamSplitter::Status pop_paf_client(Flow* ssn, PopPafData* pfdata, if (find_data_end_single_line(pfdata, ch, true) ) { // reset command parsing data + pfdata->client_bytes_seen = 0; *fp = i + 1; return StreamSplitter::FLUSH; } break; + case POP_CMD_INVALID: + if (find_data_end_single_line(pfdata, ch, true)) + { + pfdata->client_bytes_seen += len; + if(pfdata->client_bytes_seen > POP_MAX_OCTETS) + { + pfdata->client_bytes_seen = 0; + reset_client_cmd_info(pfdata); + return StreamSplitter::ABORT; + } + *fp = i + 1; + return StreamSplitter::FLUSH; + } + break; case POP_CMD_ARG: if (find_data_end_single_line(pfdata, ch, true)) { + pfdata->client_bytes_seen = 0; set_server_state(ssn, POP_PAF_MULTI_LINE_STATE); *fp = i + 1; return StreamSplitter::FLUSH; @@ -355,6 +422,13 @@ static StreamSplitter::Status pop_paf_client(Flow* ssn, PopPafData* pfdata, } } + pfdata->client_bytes_seen += len; + if(pfdata->client_bytes_seen > POP_MAX_OCTETS) + { + reset_client_cmd_info(pfdata); + return StreamSplitter::ABORT; + } + return StreamSplitter::SEARCH; } @@ -366,6 +440,7 @@ PopSplitter::PopSplitter(bool c2s) : StreamSplitter(c2s) { memset(&state, 0, sizeof(state)); reset_data_states(&state); + reset_client_cmd_info(&state); } diff --git a/src/service_inspectors/pop/pop_paf.h b/src/service_inspectors/pop/pop_paf.h index c14660553..da3ad225f 100644 --- a/src/service_inspectors/pop/pop_paf.h +++ b/src/service_inspectors/pop/pop_paf.h @@ -27,6 +27,7 @@ #include "mime/file_mime_paf.h" #include "stream/stream_splitter.h" +#define POP_MAX_OCTETS 5120 // Structure used to record expected server termination sequence enum PopExpectedResp { @@ -40,7 +41,8 @@ enum PopParseCmdState { POP_CMD_SEARCH, // Search for Command POP_CMD_FIN, // Found space. Finished parsing Command - POP_CMD_ARG // Parsing command with multi-line response iff arg given + POP_CMD_ARG, // Parsing command with multi-line response iff arg given + POP_CMD_INVALID //Command is not recognized so finish parsing and update threshold counter }; // saves data when parsing client commands @@ -59,6 +61,8 @@ struct PopPafData DataEndState end_state; // Current termination sequence state MimeDataPafInfo data_info; // Mime Information bool cmd_continued; // data continued from previous packet? + uint32_t client_bytes_seen; + uint32_t server_bytes_seen; bool end_of_data; };