From: Maya Dagon (mdagon) Date: Fri, 21 Jul 2023 11:05:54 +0000 (+0000) Subject: Pull request #3916: detection: service_mapping config X-Git-Tag: 3.1.67.0~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d311e37cd82f3797333b6e8f5eb0d9429945bb1b;p=thirdparty%2Fsnort3.git Pull request #3916: detection: service_mapping config Merge in SNORT/snort3 from ~MDAGON/snort3:service_map to master Squashed commit of the following: commit 5188c7c6ead8b7dae5b512167470ffe949fbfd74 Author: maya dagon Date: Thu Jul 20 11:08:55 2023 -0400 ips_options: remove FIXIT comment from SD_Pattern commit a08b568ab39443470dba17ae278cbf94fe43b238 Author: maya dagon Date: Fri Jul 7 14:05:01 2023 -0400 detection: service_extension config --- diff --git a/src/detection/detection_module.cc b/src/detection/detection_module.cc index 3f4a71dcb..a87a0b073 100644 --- a/src/detection/detection_module.cc +++ b/src/detection/detection_module.cc @@ -54,6 +54,26 @@ static const TraceOption detection_trace_options[] = }; #endif + +static const Parameter extend_to_service[] = +{ + { "extend_to_service", Parameter::PT_STRING, nullptr, nullptr, + "service to extend to" }, + + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } +}; + +static const Parameter service_extension[] = +{ + { "service", Parameter::PT_STRING, nullptr, nullptr, + "service to perform extension for" }, + + { "extend_to", Parameter::PT_LIST, extend_to_service, nullptr, + "comma separated list of services to extend to"}, + + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } +}; + static const Parameter detection_params[] = { { "allow_missing_so_rules", Parameter::PT_BOOL, nullptr, "false", @@ -106,6 +126,10 @@ static const Parameter detection_params[] = { "max_continuations_per_flow", Parameter::PT_INT, "0:65535", "1024", "maximum number of continuations stored simultaneously on the flow" }, + { "service_extension", Parameter::PT_LIST, service_extension, nullptr, + "List of maps outlining single service extension to multiple services " + "(defaults to http:http2,http3; netbios-ssn:dcerpc)" }, + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } }; /* *INDENT-ON* */ @@ -130,8 +154,48 @@ const TraceOption* DetectionModule::get_trace_options() const #endif } -bool DetectionModule::end(const char*, int, SnortConfig* sc) +bool DetectionModule::begin(const char* fqn, int idx, SnortConfig* sc) { + if ( !strcmp(fqn, "detection.service_extension") and ( idx == 0 ) ) + sc->service_extension.clear(); + + return true; +} + +bool DetectionModule::add_service_extension(SnortConfig* sc) +{ + const bool ok = (sc->service_extension.insert({service, extend_to})).second; + if (!ok) + ParseWarning(WARN_CONF,"Duplicate service entry %s in service extension\n", service.c_str()); + service.clear(); + extend_to.clear(); + return true; +} + +bool DetectionModule::end(const char* fqn, int idx, SnortConfig* sc) +{ + if ( !strcmp(fqn, "detection.service_extension") ) + { + if ( idx == 0 and service.empty() and extend_to.empty() ) + return true; + + if ( service.empty() ) + { + ParseError("An entry in detection.service_extension missing a service name"); + extend_to.clear(); + return true; + } + + if ( extend_to.empty() ) + { + ParseError("Service %s in detection.service_extension missing extend_to", service.c_str()); + service.clear(); + return true; + } + + return add_service_extension(sc); + } + if ( sc->offload_threads and ThreadConfig::get_instance_max() != 1 ) ParseError("You can not enable experimental offload with more than one packet thread."); @@ -220,5 +284,11 @@ bool DetectionModule::set(const char*, Value& v, SnortConfig* sc) else if ( v.is("max_continuations_per_flow") ) sc->max_continuations = v.get_uint16(); + else if ( v.is("service") ) + service = v.get_string(); + + else if ( v.is("extend_to_service") ) + extend_to.emplace_back(v.get_string()); + return true; } diff --git a/src/detection/detection_module.h b/src/detection/detection_module.h index 2d0f01477..862cc6bc1 100644 --- a/src/detection/detection_module.h +++ b/src/detection/detection_module.h @@ -31,6 +31,7 @@ class DetectionModule : public Module public: DetectionModule(); + bool begin(const char*, int, snort::SnortConfig*) override; bool set(const char*, Value&, SnortConfig*) override; bool end(const char*, int, SnortConfig*) override; @@ -45,6 +46,12 @@ public: void set_trace(const Trace*) const override; const TraceOption* get_trace_options() const override; + +private: + bool add_service_extension(snort::SnortConfig*); + + std::string service; + std::vector extend_to; }; } diff --git a/src/detection/fp_utils.cc b/src/detection/fp_utils.cc index 094be3b48..066f310c8 100644 --- a/src/detection/fp_utils.cc +++ b/src/detection/fp_utils.cc @@ -140,23 +140,11 @@ void update_buffer_map(const char** bufs, const char* svc) return; } - // FIXIT-M update NHI and H2I api.buffers and remove the hard-coded foo below for ( int i = 0; bufs[i]; ++i ) - { buffer_map[bufs[i]].push_back(svc); - if ( !strcmp(svc, "http") ) - { - buffer_map[bufs[i]].push_back("http2"); - buffer_map[bufs[i]].push_back("http3"); - } - } if ( !strcmp(svc, "http") ) - { buffer_map["file_data"].push_back("http"); - buffer_map["file_data"].push_back("http2"); - buffer_map["file_data"].push_back("http3"); - } } void add_default_services(SnortConfig* sc, const std::string& buf, OptTreeNode* otn) @@ -501,35 +489,41 @@ void validate_services(SnortConfig* sc, OptTreeNode* otn) continue; CursorActionType cat = ofl->ips_opt->get_cursor_type(); - const char* s = ofl->ips_opt->get_name(); + const char* opt = ofl->ips_opt->get_name(); if ( cat <= CAT_ADJUST ) { if ( !guess ) - guess = guess_service(s); + guess = guess_service(opt); continue; } - unsigned n = get_num_services(s); + unsigned n = get_num_services(opt); if ( !n ) continue; if ( n > 1 ) { - multi_svc_buf = s; + multi_svc_buf = opt; continue; } - s = get_service(s); + const char* opt_svc = get_service(opt); + const auto& search = sc->service_extension.find(opt_svc); + if (search != sc->service_extension.end()) + { + multi_svc_buf = opt; + continue; + } - if ( !svc.empty() and svc != s ) + if ( !svc.empty() and svc != opt_svc ) { ParseWarning(WARN_RULES, "%u:%u:%u has mixed service buffers (%s and %s)", - otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev, svc.c_str(), s); + otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev, svc.c_str(), opt_svc); } - svc = s; + svc = opt_svc; } if ( !svc.empty() or !multi_svc_buf.empty() or guess ) @@ -561,9 +555,6 @@ void validate_services(SnortConfig* sc, OptTreeNode* otn) otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev, guess); add_service_to_otn(sc, otn, guess); - - if ( !strcmp(guess, "netbios-ssn") ) // :( - add_service_to_otn(sc, otn, "dcerpc"); } } diff --git a/src/ips_options/ips_sd_pattern.cc b/src/ips_options/ips_sd_pattern.cc index c4ea15370..dc671a180 100644 --- a/src/ips_options/ips_sd_pattern.cc +++ b/src/ips_options/ips_sd_pattern.cc @@ -223,7 +223,7 @@ bool SdPatternOption::operator==(const IpsOption& ips) const const SdPatternOption& rhs = static_cast(ips); - if ( config == rhs.config ) // FIXIT-H seems incorrect + if ( config == rhs.config ) return true; return false; diff --git a/src/main/snort_config.h b/src/main/snort_config.h index d0d87f4d0..3d20cd31c 100644 --- a/src/main/snort_config.h +++ b/src/main/snort_config.h @@ -237,6 +237,12 @@ public: bool enable_strict_reduction = false; uint16_t max_continuations = 1024; + std::unordered_map> service_extension = + { + { "http", {"http2", "http3"} }, + { "netbios-ssn", {"dcerpc"} }, + }; + //------------------------------------------------------ // process stuff diff --git a/src/parser/parse_conf.cc b/src/parser/parse_conf.cc index 81600eba2..1777b203d 100644 --- a/src/parser/parse_conf.cc +++ b/src/parser/parse_conf.cc @@ -250,6 +250,18 @@ void ParseIpVar(const char* var, const char* value) } } +static void add_service_to_otn_helper(SnortConfig* sc, OptTreeNode* otn, const char* svc_name) +{ + SnortProtocolId svc_id = sc->proto_ref->add(svc_name); + + for ( const auto& si : otn->sigInfo.services ) + if ( si.snort_protocol_id == svc_id ) + return; // already added + + SignatureServiceInfo si(svc_name, svc_id); + otn->sigInfo.services.emplace_back(si); +} + void add_service_to_otn(SnortConfig* sc, OptTreeNode* otn, const char* svc_name) { if ( !strcmp(svc_name, "file") and otn->sigInfo.services.empty() ) @@ -262,20 +274,13 @@ void add_service_to_otn(SnortConfig* sc, OptTreeNode* otn, const char* svc_name) return; } - if ( !strcmp(svc_name, "http") ) + add_service_to_otn_helper(sc, otn, svc_name); + const auto& search = sc->service_extension.find(svc_name); + if ( search != sc->service_extension.end() ) { - add_service_to_otn(sc, otn, "http2"); - add_service_to_otn(sc, otn, "http3"); + for ( const auto& svc : search->second) + add_service_to_otn_helper(sc, otn, svc.c_str()); } - - SnortProtocolId svc_id = sc->proto_ref->add(svc_name); - - for ( const auto& si : otn->sigInfo.services ) - if ( si.snort_protocol_id == svc_id ) - return; // already added - - SignatureServiceInfo si(svc_name, svc_id); - otn->sigInfo.services.emplace_back(si); } ListHead* get_rule_list(SnortConfig* sc, const char* s)