From: Tom Peters (thopeter) Date: Wed, 17 Aug 2022 23:52:41 +0000 (+0000) Subject: Pull request #3555: http_inspect: parameters for header alerts X-Git-Tag: 3.1.40.0~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=109d7d5f0771a0c2df29268b4502de1fde5a9729;p=thirdparty%2Fsnort3.git Pull request #3555: http_inspect: parameters for header alerts Merge in SNORT/snort3 from ~ADMAMOLE/snort3:header_params to master Squashed commit of the following: commit beed48e8b60e9631ff9001b79db3dfd9df3e4285 Author: Adrian Mamolea Date: Mon Aug 8 17:06:08 2022 -0400 http_inspect: parameters for header alerts --- diff --git a/doc/reference/builtin_stubs.txt b/doc/reference/builtin_stubs.txt index 52eec8bcf..e3b97c2b8 100644 --- a/doc/reference/builtin_stubs.txt +++ b/doc/reference/builtin_stubs.txt @@ -809,12 +809,12 @@ generated if the simplify_path option is configured. 119:19 -HTTP header line exceeds 4096 bytes. This does not apply to the start line. Header line length -includes both header field name and value. +HTTP header line exceeds maximum_header_length option bytes. This does not apply to the start line. +Header line length includes both header field name and value. 119:20 -HTTP message has more than 200 header fields. +HTTP message has more than maximum_headers option header fields. 119:21 diff --git a/doc/user/http_inspect.txt b/doc/user/http_inspect.txt index b09c48219..badafdd73 100755 --- a/doc/user/http_inspect.txt +++ b/doc/user/http_inspect.txt @@ -343,6 +343,16 @@ body to be less than four gigabytes. A lower limit may be configured by setting maximum_chunk_length. Any chunk longer than maximum chunk length will generate a 119:16 alert. +===== maximum_header_length + +http_inspect generates 119:19 when the length of a header exceeds +maximum_header_length = N {0 : 65535} (default 4096). + +===== maximum_headers + +http_inspect generates 119:20 when the number of headers exceeds +maximum_headers = N {0 : 65535} (default 200). + ===== URI processing Normalization and inspection of the URI in the HTTP request message is a diff --git a/src/service_inspectors/http_inspect/http_module.cc b/src/service_inspectors/http_inspect/http_module.cc index c7451e906..a5ac07f13 100755 --- a/src/service_inspectors/http_inspect/http_module.cc +++ b/src/service_inspectors/http_inspect/http_module.cc @@ -74,6 +74,12 @@ const Parameter HttpModule::http_params[] = { "maximum_chunk_length", Parameter::PT_INT, "0:4294967295", "4294967295", "maximum allowed length for a message body chunk" }, + { "maximum_header_length", Parameter::PT_INT, "0:65535", "4096", + "alert when the length of a header exceeds this value" }, + + { "maximum_headers", Parameter::PT_INT, "0:65535", "200", + "alert when the number of headers in a message exceeds this value" }, + { "normalize_utf", Parameter::PT_BOOL, nullptr, "true", "normalize charset utf encodings in response bodies" }, @@ -254,6 +260,14 @@ bool HttpModule::set(const char*, Value& val, SnortConfig*) { params->maximum_chunk_length = val.get_int64(); } + else if (val.is("maximum_header_length")) + { + params->maximum_header_length = val.get_uint16(); + } + else if (val.is("maximum_headers")) + { + params->maximum_headers = val.get_uint16(); + } else if (val.is("decompress_pdf")) { params->decompress_pdf = val.get_bool(); diff --git a/src/service_inspectors/http_inspect/http_module.h b/src/service_inspectors/http_inspect/http_module.h index 35dce8d00..7b0070c81 100755 --- a/src/service_inspectors/http_inspect/http_module.h +++ b/src/service_inspectors/http_inspect/http_module.h @@ -54,6 +54,8 @@ public: bool normalize_utf = true; int64_t maximum_host_length = -1; int64_t maximum_chunk_length = 0xFFFFFFFF; + uint16_t maximum_header_length = 4096; + uint16_t maximum_headers = 200; bool decompress_pdf = false; bool decompress_swf = false; bool decompress_zip = false; diff --git a/src/service_inspectors/http_inspect/http_msg_head_shared.cc b/src/service_inspectors/http_inspect/http_msg_head_shared.cc index 15ad80d13..ee3ea1b2e 100755 --- a/src/service_inspectors/http_inspect/http_msg_head_shared.cc +++ b/src/service_inspectors/http_inspect/http_msg_head_shared.cc @@ -132,18 +132,15 @@ void HttpMsgHeadShared::parse_header_block() const int32_t header_length = find_next_header(msg_text.start() + bytes_used, msg_text.length() - bytes_used, num_seps); header_line[num_headers].set(header_length, msg_text.start() + bytes_used + num_seps); - if (header_line[num_headers].length() > MAX_HEADER_LENGTH) + if (header_line[num_headers].length() > params->maximum_header_length) { add_infraction(INF_TOO_LONG_HEADER); create_event(EVENT_LONG_HDR); } bytes_used += num_seps + header_line[num_headers].length(); - if (++num_headers >= MAX_HEADERS) - { - break; - } + ++num_headers; } - if (bytes_used < msg_text.length()) + if (num_headers > params->maximum_headers) { add_infraction(INF_TOO_MANY_HEADERS); create_event(EVENT_MAX_HEADERS); diff --git a/src/service_inspectors/http_inspect/http_msg_head_shared.h b/src/service_inspectors/http_inspect/http_msg_head_shared.h index 61db916b4..144aa9761 100755 --- a/src/service_inspectors/http_inspect/http_msg_head_shared.h +++ b/src/service_inspectors/http_inspect/http_msg_head_shared.h @@ -62,7 +62,6 @@ public: int32_t get_num_headers() const { return num_headers; } int32_t get_content_type(); - static const int MAX_HEADERS = 200; // I'm an arbitrary number. FIXIT-RC protected: HttpMsgHeadShared(const uint8_t* buffer, const uint16_t buf_size, HttpFlowData* session_data_, HttpCommon::SourceId source_id_, bool buf_owner, snort::Flow* flow_, @@ -73,6 +72,8 @@ protected: // Do a case insensitive search for "boundary=" in a Field static bool boundary_present(const Field& field); + // All of these are indexed by the relative position of the header field in the message + Field* header_line = nullptr; HttpEnums::HeaderId* header_name_id = nullptr; int32_t num_headers = HttpCommon::STAT_NOT_COMPUTE; @@ -84,9 +85,6 @@ protected: private: static const int MAX = HttpEnums::HEAD__MAX_VALUE + HttpEnums::MAX_CUSTOM_HEADERS; - // All of these are indexed by the relative position of the header field in the message - static const int MAX_HEADER_LENGTH = 4096; // Based on max cookie size of some browsers - void parse_header_block(); int32_t find_next_header(const uint8_t* buffer, int32_t length, int32_t& num_seps); void parse_header_lines(); diff --git a/src/service_inspectors/http_inspect/http_tables.cc b/src/service_inspectors/http_inspect/http_tables.cc index 35881af73..ff7dc6f1e 100755 --- a/src/service_inspectors/http_inspect/http_tables.cc +++ b/src/service_inspectors/http_inspect/http_tables.cc @@ -241,8 +241,8 @@ const RuleMap HttpModule::http_events[] = "oversize_dir_length parameter" }, { EVENT_LARGE_CHUNK, "chunk length exceeds configured maximum_chunk_length" }, { EVENT_WEBROOT_DIR, "URI path includes /../ that goes above the root directory" }, - { EVENT_LONG_HDR, "HTTP header line exceeds 4096 bytes" }, - { EVENT_MAX_HEADERS, "HTTP message has more than 200 header fields" }, + { EVENT_LONG_HDR, "HTTP header line exceeds maximum_header_length option bytes" }, + { EVENT_MAX_HEADERS, "HTTP message has more than maximum_headers option header fields" }, { EVENT_MULTIPLE_CONTLEN, "HTTP message has more than one Content-Length header value" }, { EVENT_MULTIPLE_HOST_HDRS, "Host header field appears more than once or has multiple values" }, { EVENT_LONG_HOSTNAME, "length of HTTP Host header field value exceeds maximum_host_length option" },