From: Mike Stepanek (mstepane) Date: Mon, 11 Jan 2021 13:38:56 +0000 (+0000) Subject: Merge pull request #2692 in SNORT/snort3 from ~MDAGON/snort3:nhi_alert to master X-Git-Tag: 3.1.0.0~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b2197dba717900c42d1e8a275e46e99411802523;p=thirdparty%2Fsnort3.git Merge pull request #2692 in SNORT/snort3 from ~MDAGON/snort3:nhi_alert to master Squashed commit of the following: commit 45db5f4a4e9eadc2ddb6565824ed3407063b4307 Author: mdagon Date: Tue Dec 22 15:44:07 2020 -0500 http_inspect: alert on truncated chunked and content-length message bodies --- diff --git a/src/service_inspectors/http_inspect/http_enum.h b/src/service_inspectors/http_inspect/http_enum.h index 7be0f0f7a..cae4b20c7 100755 --- a/src/service_inspectors/http_inspect/http_enum.h +++ b/src/service_inspectors/http_inspect/http_enum.h @@ -244,6 +244,8 @@ enum Infraction INF_EARLY_CONNECT_RESPONSE, INF_MALFORMED_CD_FILENAME, INF_HTTP2_IN_HI, + INF_TRUNCATED_MSG_BODY_CL, + INF_TRUNCATED_MSG_BODY_CHUNK, INF__MAX_VALUE }; @@ -372,6 +374,8 @@ enum EventSid EVENT_100_CONNECT_RESP, EVENT_EARLY_CONNECT_RESPONSE, // 258 EVENT_MALFORMED_CD_FILENAME, + EVENT_TRUNCATED_MSG_BODY_CL, + EVENT_TRUNCATED_MSG_BODY_CHUNK, EVENT__MAX_VALUE }; diff --git a/src/service_inspectors/http_inspect/http_stream_splitter_finish.cc b/src/service_inspectors/http_inspect/http_stream_splitter_finish.cc index 0cd6adff9..a67bfcd35 100644 --- a/src/service_inspectors/http_inspect/http_stream_splitter_finish.cc +++ b/src/service_inspectors/http_inspect/http_stream_splitter_finish.cc @@ -42,7 +42,7 @@ bool HttpStreamSplitter::finish(Flow* flow) Profile profile(HttpModule::get_profile_stats()); HttpFlowData* session_data = HttpInspect::http_get_flow_data(flow); - if(!session_data) + if (!session_data) return false; #ifdef REG_TEST @@ -69,14 +69,26 @@ bool HttpStreamSplitter::finish(Flow* flow) } session_data->tcp_close[source_id] = true; + if (session_data->section_type[source_id] != SEC__NOT_COMPUTE) + return true; + + if (session_data->type_expected[source_id] == SEC_BODY_CL) + { + *session_data->get_infractions(source_id) += INF_TRUNCATED_MSG_BODY_CL; + session_data->events[source_id]->create_event(EVENT_TRUNCATED_MSG_BODY_CL); + } + else if (session_data->type_expected[source_id] == SEC_BODY_CHUNK) + { + *session_data->get_infractions(source_id) += INF_TRUNCATED_MSG_BODY_CHUNK; + session_data->events[source_id]->create_event(EVENT_TRUNCATED_MSG_BODY_CHUNK); + } // If there is leftover data for which we returned PAF_SEARCH and never flushed, we need to set // up to process because it is about to go to reassemble(). But we don't support partial start // lines. - if ((session_data->section_type[source_id] == SEC__NOT_COMPUTE) && - (session_data->cutter[source_id] != nullptr) && + if ((session_data->cutter[source_id] != nullptr) && (session_data->cutter[source_id]->get_octets_seen() > - session_data->partial_raw_bytes[source_id])) + session_data->partial_raw_bytes[source_id])) { if ((session_data->type_expected[source_id] == SEC_REQUEST) || (session_data->type_expected[source_id] == SEC_STATUS)) @@ -104,8 +116,7 @@ bool HttpStreamSplitter::finish(Flow* flow) // process an empty header section to provide an inspection section. Otherwise the start line // won't go through detection. if ((session_data->type_expected[source_id] == SEC_HEADER) && - (session_data->cutter[source_id] == nullptr) && - (session_data->section_type[source_id] == SEC__NOT_COMPUTE)) + (session_data->cutter[source_id] == nullptr)) { // Set up to process empty header section uint32_t not_used; @@ -114,8 +125,7 @@ bool HttpStreamSplitter::finish(Flow* flow) } // If there is no more data to process we need to wrap up file processing right now - if ((session_data->section_type[source_id] == SEC__NOT_COMPUTE) && - (session_data->file_depth_remaining[source_id] > 0) && + if ((session_data->file_depth_remaining[source_id] > 0) && (session_data->cutter[source_id] != nullptr) && (session_data->cutter[source_id]->get_octets_seen() == session_data->partial_raw_bytes[source_id])) @@ -165,7 +175,7 @@ bool HttpStreamSplitter::finish(Flow* flow) return false; } - return session_data->section_type[source_id] != SEC__NOT_COMPUTE; + return false; } bool HttpStreamSplitter::init_partial_flush(Flow* flow, uint32_t num_flush) @@ -178,9 +188,9 @@ bool HttpStreamSplitter::init_partial_flush(Flow* flow, uint32_t num_flush) assert(session_data->for_http2 || source_id == SRC_SERVER); assert((session_data->type_expected[source_id] == SEC_BODY_CL) || - (session_data->type_expected[source_id] == SEC_BODY_OLD) || - (session_data->type_expected[source_id] == SEC_BODY_CHUNK) || - (session_data->type_expected[source_id] == SEC_BODY_H2)); + (session_data->type_expected[source_id] == SEC_BODY_OLD) || + (session_data->type_expected[source_id] == SEC_BODY_CHUNK) || + (session_data->type_expected[source_id] == SEC_BODY_H2)); #ifdef REG_TEST if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP) && diff --git a/src/service_inspectors/http_inspect/http_tables.cc b/src/service_inspectors/http_inspect/http_tables.cc index 4e45865fb..16207e0d6 100755 --- a/src/service_inspectors/http_inspect/http_tables.cc +++ b/src/service_inspectors/http_inspect/http_tables.cc @@ -404,6 +404,8 @@ const RuleMap HttpModule::http_events[] = { EVENT_100_CONNECT_RESP, "HTTP CONNECT response with 1XX status code" }, { EVENT_EARLY_CONNECT_RESPONSE, "HTTP CONNECT response before request message completed" }, { EVENT_MALFORMED_CD_FILENAME, "malformed HTTP Content-Disposition filename parameter" }, + { EVENT_TRUNCATED_MSG_BODY_CL, "HTTP Content-Length message body was truncated" }, + { EVENT_TRUNCATED_MSG_BODY_CHUNK, "HTTP chunked message body was truncated" }, { 0, nullptr } };