From ee8d5c2eda44cd458a61b58b4ecca2d1d1565553 Mon Sep 17 00:00:00 2001 From: "Tom Peters (thopeter)" Date: Wed, 21 Jul 2021 17:52:36 +0000 Subject: [PATCH] Merge pull request #2988 in SNORT/snort3 from ~MDAGON/snort3:complete to master Squashed commit of the following: commit 605e1f86c087e13ed7a459cd75559ad6ee7b8b00 Author: Maya Dagon Date: Mon Jul 12 16:57:25 2021 -0400 http_inspect: add rule option http_raw_header_complete --- doc/user/http_inspect.txt | 16 +++--- .../http_inspect/http_api.cc | 3 + .../http_inspect/http_enum.h | 2 +- .../http_inspect/http_msg_header.cc | 2 + .../http_inspect/http_msg_section.cc | 5 ++ .../http_inspect/ips_http.cc | 55 +++++++++++++++++++ .../http_inspect/ips_http.h | 4 +- 7 files changed, 77 insertions(+), 10 deletions(-) diff --git a/doc/user/http_inspect.txt b/doc/user/http_inspect.txt index cb7df1eb1..43b60f565 100755 --- a/doc/user/http_inspect.txt +++ b/doc/user/http_inspect.txt @@ -417,7 +417,7 @@ Note: this section uses informal language to explain some things. Nothing here is intended to conflict with the technical language of the HTTP RFCs and the implementation follows the RFCs. -===== http_header and http_raw_header +===== http_header, http_raw_header, and http_raw_header_complete These cover all the header lines except the first one. You may specify an individual header by name using the field option as shown in this earlier @@ -434,13 +434,15 @@ upper and lower case. With http_header the individual header value is normalized in a way that is appropriate for that header. -Specifying an individual header is not available for http_raw_header. +Specifying an individual header is not available for http_raw_header and +http_raw_header_complete. -If you don't specify a header you get all of the headers except for the -cookie headers Cookie and Set-Cookie. http_raw_header includes the -unmodified header names and values as they appeared in the original -message. http_header is the same except percent encodings are removed and -paths are simplified exactly as if the headers were a URI. +If you don't specify a header you get all of the headers. http_raw_header_complete +includes cookie headers Cookie and Set-Cookie. http_header and http_raw_header don't. +http_raw_header and http_raw_header_complete include the unmodified header names +and values as they appeared in the original message. http_header is the same except +percent encodings are removed and paths are simplified exactly as if the headers +were a URI. In most cases specifying individual headers creates a more efficient and accurate rule. It is recommended that new rules be written using individual diff --git a/src/service_inspectors/http_inspect/http_api.cc b/src/service_inspectors/http_inspect/http_api.cc index 9cae42e56..fc9da8be5 100644 --- a/src/service_inspectors/http_inspect/http_api.cc +++ b/src/service_inspectors/http_inspect/http_api.cc @@ -57,6 +57,7 @@ const char* HttpApi::classic_buffer_names[] = "http_raw_body", "http_raw_cookie", "http_raw_header", + "http_raw_header_complete", "http_raw_request", "http_raw_status", "http_raw_trailer", @@ -106,6 +107,7 @@ extern const BaseApi* ips_http_param; extern const BaseApi* ips_http_raw_body; extern const BaseApi* ips_http_raw_cookie; extern const BaseApi* ips_http_raw_header; +extern const BaseApi* ips_http_raw_header_complete; extern const BaseApi* ips_http_raw_request; extern const BaseApi* ips_http_raw_status; extern const BaseApi* ips_http_raw_trailer; @@ -132,6 +134,7 @@ const BaseApi* sin_http[] = ips_http_raw_body, ips_http_raw_cookie, ips_http_raw_header, + ips_http_raw_header_complete, ips_http_raw_request, ips_http_raw_status, ips_http_raw_trailer, diff --git a/src/service_inspectors/http_inspect/http_enum.h b/src/service_inspectors/http_inspect/http_enum.h index 51cd88432..31b60846e 100755 --- a/src/service_inspectors/http_inspect/http_enum.h +++ b/src/service_inspectors/http_inspect/http_enum.h @@ -51,7 +51,7 @@ enum DetectionStatus { DET_REACTIVATING = 1, DET_ON, DET_DEACTIVATING, DET_OFF } // This enum must remain synchronized with HttpApi::classic_buffer_names[] enum HTTP_BUFFER { HTTP_BUFFER_CLIENT_BODY = 1, HTTP_BUFFER_COOKIE, HTTP_BUFFER_HEADER, HTTP_BUFFER_METHOD, HTTP_BUFFER_PARAM, HTTP_BUFFER_RAW_BODY, HTTP_BUFFER_RAW_COOKIE, - HTTP_BUFFER_RAW_HEADER, HTTP_BUFFER_RAW_REQUEST, HTTP_BUFFER_RAW_STATUS, + HTTP_BUFFER_RAW_HEADER, HTTP_BUFFER_RAW_HEADER_COMPLETE, HTTP_BUFFER_RAW_REQUEST, HTTP_BUFFER_RAW_STATUS, HTTP_BUFFER_RAW_TRAILER, HTTP_BUFFER_RAW_URI, HTTP_BUFFER_STAT_CODE, HTTP_BUFFER_STAT_MSG, HTTP_BUFFER_TRAILER, HTTP_BUFFER_TRUE_IP, HTTP_BUFFER_URI, HTTP_BUFFER_VERSION, HTTP_BUFFER_MAX }; diff --git a/src/service_inspectors/http_inspect/http_msg_header.cc b/src/service_inspectors/http_inspect/http_msg_header.cc index 31f7e71b2..da3ae1c45 100755 --- a/src/service_inspectors/http_inspect/http_msg_header.cc +++ b/src/service_inspectors/http_inspect/http_msg_header.cc @@ -681,6 +681,8 @@ void HttpMsgHeader::print_section(FILE* output) HttpApi::classic_buffer_names[HTTP_BUFFER_RAW_COOKIE-1]); get_classic_buffer(HTTP_BUFFER_RAW_HEADER, 0, 0).print(output, HttpApi::classic_buffer_names[HTTP_BUFFER_RAW_HEADER-1]); + get_classic_buffer(HTTP_BUFFER_RAW_HEADER_COMPLETE, 0, 0).print(output, + HttpApi::classic_buffer_names[HTTP_BUFFER_RAW_HEADER_COMPLETE-1]); HttpMsgSection::print_section_wrapup(output); } #endif diff --git a/src/service_inspectors/http_inspect/http_msg_section.cc b/src/service_inspectors/http_inspect/http_msg_section.cc index 110fb6d94..4eb99daa3 100644 --- a/src/service_inspectors/http_inspect/http_msg_section.cc +++ b/src/service_inspectors/http_inspect/http_msg_section.cc @@ -321,6 +321,11 @@ const Field& HttpMsgSection::get_classic_buffer(Cursor& c, const HttpBufferInfo& return (header[buffer_side] != nullptr) ? header[buffer_side]->get_classic_raw_header() : Field::FIELD_NULL; } + case HTTP_BUFFER_RAW_HEADER_COMPLETE: + { + return (header[buffer_side] != nullptr) ? header[buffer_side]->msg_text : + Field::FIELD_NULL; + } case HTTP_BUFFER_RAW_REQUEST: { return (request != nullptr) ? request->msg_text : Field::FIELD_NULL; diff --git a/src/service_inspectors/http_inspect/ips_http.cc b/src/service_inspectors/http_inspect/ips_http.cc index a2d22a995..2eaf8d707 100644 --- a/src/service_inspectors/http_inspect/ips_http.cc +++ b/src/service_inspectors/http_inspect/ips_http.cc @@ -61,6 +61,7 @@ bool HttpCursorModule::begin(const char*, int, SnortConfig*) case HTTP_BUFFER_PARAM: case HTTP_BUFFER_RAW_COOKIE: case HTTP_BUFFER_RAW_HEADER: + case HTTP_BUFFER_RAW_HEADER_COMPLETE: case HTTP_BUFFER_RAW_REQUEST: case HTTP_BUFFER_RAW_URI: case HTTP_BUFFER_TRUE_IP: @@ -664,6 +665,59 @@ static const IpsApi raw_header_api = nullptr }; +//------------------------------------------------------------------------- +// http_raw_header_complete +//------------------------------------------------------------------------- + +static const Parameter http_raw_header_complete_params[] = +{ + { "request", Parameter::PT_IMPLIED, nullptr, nullptr, + "match against the headers from the request message even when examining the response" }, + { "with_header", Parameter::PT_IMPLIED, nullptr, nullptr, + "this rule is limited to examining HTTP message headers" }, + { "with_body", Parameter::PT_IMPLIED, nullptr, nullptr, + "parts of this rule examine HTTP message body" }, + { "with_trailer", Parameter::PT_IMPLIED, nullptr, nullptr, + "parts of this rule examine HTTP message trailers" }, + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } +}; + +#undef IPS_OPT +#define IPS_OPT "http_raw_header_complete" +#undef IPS_HELP +#define IPS_HELP "rule option to set the detection cursor to the unnormalized headers including cookies" + +static Module* raw_header_complete_mod_ctor() +{ + return new HttpCursorModule(IPS_OPT, IPS_HELP, HTTP_BUFFER_RAW_HEADER_COMPLETE, + CAT_SET_OTHER, PSI_RAW_HEADER_COMPLETE, http_raw_header_complete_params); +} + +static const IpsApi raw_header_complete_api = +{ + { + PT_IPS_OPTION, + sizeof(IpsApi), + IPSAPI_VERSION, + 1, + API_RESERVED, + API_OPTIONS, + IPS_OPT, + IPS_HELP, + raw_header_complete_mod_ctor, + HttpCursorModule::mod_dtor + }, + OPT_TYPE_DETECTION, + 0, PROTO_BIT__TCP, + nullptr, + nullptr, + nullptr, + nullptr, + HttpIpsOption::opt_ctor, + HttpIpsOption::opt_dtor, + nullptr +}; + //------------------------------------------------------------------------- // http_raw_request //------------------------------------------------------------------------- @@ -1209,6 +1263,7 @@ const BaseApi* ips_http_param = ¶m_api.base; const BaseApi* ips_http_raw_body = &raw_body_api.base; const BaseApi* ips_http_raw_cookie = &raw_cookie_api.base; const BaseApi* ips_http_raw_header = &raw_header_api.base; +const BaseApi* ips_http_raw_header_complete = &raw_header_complete_api.base; const BaseApi* ips_http_raw_request = &raw_request_api.base; const BaseApi* ips_http_raw_status = &raw_status_api.base; const BaseApi* ips_http_raw_trailer = &raw_trailer_api.base; diff --git a/src/service_inspectors/http_inspect/ips_http.h b/src/service_inspectors/http_inspect/ips_http.h index 25d9d60c8..469e849bb 100644 --- a/src/service_inspectors/http_inspect/ips_http.h +++ b/src/service_inspectors/http_inspect/ips_http.h @@ -30,8 +30,8 @@ #include "http_enum.h" enum PsIdx { PSI_CLIENT_BODY, PSI_COOKIE, PSI_HEADER, PSI_METHOD, PSI_PARAM, - PSI_RAW_BODY, PSI_RAW_COOKIE, PSI_RAW_HEADER, PSI_RAW_REQUEST, PSI_RAW_STATUS, - PSI_RAW_TRAILER, PSI_RAW_URI, PSI_STAT_CODE, PSI_STAT_MSG, PSI_TRAILER, + PSI_RAW_BODY, PSI_RAW_COOKIE, PSI_RAW_HEADER, PSI_RAW_HEADER_COMPLETE, PSI_RAW_REQUEST, + PSI_RAW_STATUS, PSI_RAW_TRAILER, PSI_RAW_URI, PSI_STAT_CODE, PSI_STAT_MSG, PSI_TRAILER, PSI_TRUE_IP, PSI_URI, PSI_VERSION, PSI_MAX }; class HttpCursorModule : public snort::Module -- 2.47.3