#include "ips_signatures.h" #include #include #include "ips_comp.h" #include "ips_basic_policy.h" #include "snort_basic_policy.h" #include "generic_rulebase/parameters_config.h" #include "generic_rulebase/triggers_config.h" #include "rule_detection.h" #include "helper.h" #include "config.h" #include "context.h" #include "ips_entry.h" #include "ips_metric.h" #include "ips_common_types.h" USE_DEBUG_FLAG(D_IPS); using namespace IPSSignatureSubTypes; using namespace ReportIS; using namespace std; using MatchType = BaseSignature::MatchType; static const LogTriggerConf default_triger; static const map severities = { { IPSLevel::CRITICAL, Severity::CRITICAL }, { IPSLevel::HIGH, Severity::HIGH }, { IPSLevel::MEDIUM_HIGH, Severity::HIGH }, { IPSLevel::MEDIUM, Severity::MEDIUM }, { IPSLevel::MEDIUM_LOW, Severity::LOW }, { IPSLevel::LOW, Severity::LOW }, { IPSLevel::VERY_LOW, Severity::INFO } }; static const map levels = { { "Critical", IPSLevel::CRITICAL }, { "High", IPSLevel::HIGH }, { "Medium High", IPSLevel::MEDIUM_HIGH }, { "Medium", IPSLevel::MEDIUM }, { "Medium Low", IPSLevel::MEDIUM_LOW }, { "Low", IPSLevel::LOW }, { "Very Low", IPSLevel::VERY_LOW } }; static IPSLevel getLevel(const string &level_string, const string &attr_name) { auto index = levels.find(level_string); if (index == levels.end()) { reportConfigurationError( "Unknown level: '" + level_string + "' in attribute " + attr_name ); } return index->second; } void IPSSignatureMetaData::setIndicators(const string &_source, const string &_version) { source = _source; version = _version; } string IPSSignatureMetaData::getSeverityString() const { switch (severity) { case IPSLevel::VERY_LOW: return "Very Low"; case IPSLevel::LOW: return "Low"; case IPSLevel::MEDIUM_LOW: return "Medium Low"; case IPSLevel::MEDIUM: return "Medium"; case IPSLevel::MEDIUM_HIGH: return "Medium High"; case IPSLevel::HIGH: return "High"; case IPSLevel::CRITICAL: return "Critical"; } dbgAssert(false) << AlertInfo(AlertTeam::CORE, "ips") << "Illegal severity value: " << static_cast(severity); return "Critical"; } string IPSSignatureMetaData::getConfidenceString() const { if (confidence <= IPSLevel::LOW) return "Low"; if (confidence >= IPSLevel::HIGH) return "High"; return "Medium"; } string IPSSignatureMetaData::getPerformanceString() const { switch (performance) { case IPSLevel::VERY_LOW: return "Very Low"; case IPSLevel::LOW: return "Low"; case IPSLevel::MEDIUM_LOW: return "Medium Low"; case IPSLevel::MEDIUM: return "Medium"; case IPSLevel::MEDIUM_HIGH: return "Medium High"; case IPSLevel::HIGH: return "High"; case IPSLevel::CRITICAL: return "Critical"; } dbgAssert(false) << AlertInfo(AlertTeam::CORE, "ips") << "Illegal performance value: " << static_cast(performance); return "Critical"; } void IPSSignatureMetaData::load(cereal::JSONInputArchive &ar) { string severity_string, confidence_string, performance_string; ar( cereal::make_nvp("maintrainId", protection_id), cereal::make_nvp("protectionName", sig_name), cereal::make_nvp("severity", severity_string), cereal::make_nvp("lastUpdate", update), cereal::make_nvp("confidenceLevel", confidence_string), cereal::make_nvp("performanceImpact", performance_string), cereal::make_nvp("cveList", cve_list), cereal::make_nvp("tags", tag_list) ); severity = getLevel(severity_string, "severity"); confidence = getLevel(confidence_string, "confidence"); performance = getLevel(performance_string, "performance"); try { ar(cereal::make_nvp("logAttackName", event_log)); } catch (cereal::Exception &) { event_log = "IPS Signature '" + sig_name + "' Found"; ar.setNextName(nullptr); } try { ar(cereal::make_nvp("silent", is_silent)); } catch (cereal::Exception &) { ar.setNextName(nullptr); } } static const size_t protection_type_pos = strlen("Protection_Type_"); static const size_t vul_type_pos = strlen("Vul_Type_"); string IPSSignatureSubTypes::IPSSignatureMetaData::getIncidentType() const { for (auto &tag : tag_list) { if (tag.compare(0, vul_type_pos, "Vul_Type_") == 0) { auto incident_type = tag.substr(vul_type_pos); replace(incident_type.begin(), incident_type.end(), '_', ' '); if (incident_type == "Vulnerability") return "Vulnerability exploit attempt"; return incident_type; } } for (auto &tag : tag_list) { if (tag.compare(0, protection_type_pos, "Protection_Type_") == 0) { auto incident_type = tag.substr(protection_type_pos); replace(incident_type.begin(), incident_type.end(), '_', ' '); if (incident_type == "Vulnerability") return "Vulnerability exploit attempt"; return incident_type; } } return ""; } static const size_t year_start_pos = strlen("Threat_Year_"); bool IPSSignatureMetaData::isYearAtLeast(const Maybe &year) const { if (!year.ok()) return true; auto protection_year = getYear(); if (!protection_year.ok()) return true; return *protection_year >= *year; } Maybe IPSSignatureMetaData::getYear() const { for (auto &tag : tag_list) { if (tag.compare(0, year_start_pos, "Threat_Year_") == 0) { if (tag.size() != year_start_pos + 4) { dbgWarning(D_IPS) << "Threat year tag (" << tag << ") doen't meet expected format"; return false; } int protection_year = (tag[year_start_pos] - '0') * 1000 + (tag[year_start_pos + 1] - '0') * 100 + (tag[year_start_pos + 2] - '0') * 10 + (tag[year_start_pos + 3] - '0'); return protection_year; } } return genError("Year not found"); } void CompleteSignature::load(cereal::JSONInputArchive &ar) { try { ar(cereal::make_nvp("protectionMetadata", metadata)); RuleDetection rule_detection(metadata.getName()); ar(cereal::make_nvp("detectionRules", rule_detection)); rule = rule_detection.getRule(); is_loaded = true; } catch (cereal::Exception &e) { is_loaded = false; dbgWarning(D_IPS) << "Failed to load signature: " << e.what(); } } MatchType CompleteSignature::getMatch(const set &matches) const { return rule->getMatch(matches); } set CompleteSignature::patternsInSignature() const { return rule->patternsInSignature(); } void CompleteSignature::setIndicators(const string &source, const string &version) { metadata.setIndicators(source, version); } template static string getSubString(const Maybe &buf, uint max_size = 0) { if (max_size == 0) max_size = buf.unpack().size(); const Buffer &real_buf = buf.unpack(); auto res = real_buf.size() <= max_size ? real_buf : real_buf.getSubBuffer(0, max_size); return static_cast(res); } ActionResults SignatureAndAction::getAction(const IPSEntry &ips_state) const { dbgDebug(D_IPS) << "matching exceptions"; unordered_map> exceptions_dict; exceptions_dict["protectionName"].insert(signature->getName()); ScopedContext ctx; ctx.registerValue("protectionName", signature->getName()); auto env = Singleton::Consume::by(); auto host = env->get(HttpTransactionData::host_name_ctx); if (host.ok()) exceptions_dict["hostName"].insert(*host); auto client_ip = env->get(HttpTransactionData::client_ip_ctx); if (client_ip.ok()) { stringstream client_ip_str; client_ip_str << client_ip.unpack(); exceptions_dict["sourceIP"].insert(client_ip_str.str()); } auto path = ips_state.getBuffer("HTTP_PATH_DECODED"); if (path.size()) exceptions_dict["url"].insert(static_cast(path)); auto env_source_identifier = env->get(HttpTransactionData::source_identifier); if (env_source_identifier.ok()) { exceptions_dict["sourceIdentifier"].insert(*env_source_identifier); } auto behaviors = getBehavior(exceptions_dict); set override_actions; vector override_ids; for (auto const &behavior : behaviors) { if (behavior.getKey() == BehaviorKey::ACTION) { override_actions.insert(behavior.getValue()); const string &override_id = behavior.getId(); if (!override_id.empty()) override_ids.push_back(override_id); } } if (override_actions.find(BehaviorValue::IGNORE) != override_actions.end()) { dbgDebug(D_IPS) << "Exception matched - action=Detect"; return make_tuple(IPSSignatureSubTypes::SignatureAction::DETECT, string("Skip"), override_ids); } if (override_actions.find(BehaviorValue::ACCEPT) != override_actions.end()) { dbgDebug(D_IPS) << "Exception matched - action=Detect"; return make_tuple(IPSSignatureSubTypes::SignatureAction::DETECT, string("Accept"), override_ids); } if (override_actions.find(BehaviorValue::REJECT) != override_actions.end()) { dbgDebug(D_IPS) << "Exception matched - action=Prevent"; return make_tuple(IPSSignatureSubTypes::SignatureAction::PREVENT, string("Drop"), override_ids); } return make_tuple(action, string("None"), override_ids); } static const auto req_body = LogTriggerConf::WebLogFields::webBody; static const auto headers = LogTriggerConf::WebLogFields::webHeaders; static const auto url_path = LogTriggerConf::WebLogFields::webUrlPath; static const auto url_query = LogTriggerConf::WebLogFields::webUrlQuery; static const auto res_body = LogTriggerConf::WebLogFields::responseBody; static const auto res_code = LogTriggerConf::WebLogFields::responseCode; LogTriggerConf SignatureAndAction::getTrigger() const { if (trigger_id.empty()) return getConfigurationWithDefault(LogTriggerConf(), "rulebase", "log"); return Singleton::Consume::by()->getLogTriggerConf(trigger_id); } set SignatureAndAction::getBehavior(const unordered_map> &exceptions_dict) const { I_GenericRulebase *i_rulebase = Singleton::Consume::by(); if (exception_id.empty()) return i_rulebase->getBehavior(exceptions_dict); return i_rulebase->getParameterException(exception_id).getBehavior(exceptions_dict); } bool SignatureAndAction::matchSilent(const Buffer &sample) const { dbgTrace(D_IPS) << "Matched silent signature"; MatchEvent(signature, IPSSignatureSubTypes::SignatureAction::IGNORE).notify(); ScopedContext ctx; ctx.registerValue("Audience Team", AudienceTeam::SIGNATURE_DEVELOPERS); LogGen log( "Silent Protection", Audience::INTERNAL, Severity::INFO, Priority::MEDIUM, LogField("practiceType", "Threat Prevention"), Tags::IPS, StreamType::JSON_FOG ); log << LogField("signatureVersion", signature->getUpdateVersion()) << LogField("protectionId", signature->getName()) << LogField("indicatorsSource", signature->getSource()) << LogField("indicatorsVersion", signature->getFeedVersion()) << LogField("incidentType", signature->getIncidentType()) << LogField("matchedSample", static_cast(sample), LogFieldOption::XORANDB64); auto env = Singleton::Consume::by(); auto table = Singleton::Consume::by(); auto &ips_state = table->getState(); auto method = env->get(HttpTransactionData::method_ctx); if (method.ok()) log << LogField("httpMethod", method.unpack()); auto path = env->get("HTTP_PATH_DECODED"); if (path.ok()) { log << LogField("httpUriPath", getSubString(path, 1536), LogFieldOption::XORANDB64); } else { auto transaction_path = env->get(HttpTransactionData::uri_path_decoded); if (transaction_path.ok()) { auto uri_path = transaction_path.unpack(); auto question_mark = uri_path.find('?'); log << LogField("httpUriPath", uri_path.substr(0, question_mark), LogFieldOption::XORANDB64); } } auto req_header = ips_state.getTransactionData(IPSCommonTypes::requests_header_for_log); if (req_header.ok()) log << LogField("httpRequestHeaders", getSubString(req_header), LogFieldOption::XORANDB64); auto res_code = env->get("HTTP_RESPONSE_CODE"); if (res_code.ok()) log << LogField("httpResponseCode", static_cast(res_code.unpack())); auto req_body = env->get("HTTP_REQUEST_BODY"); auto res_body = env->get("HTTP_RESPONSE_BODY"); uint req_size = req_body.ok() ? req_body.unpack().size() : 0; uint res_size = res_body.ok() ? res_body.unpack().size() : 0; if (req_size + res_size > 1536) { if (req_size + 500 > 1536) { res_size = std::min(500u, res_size); req_size = 1536 - res_size; } else { res_size = 1536 - req_size; } } if (req_size) log << LogField("httpRequestBody", getSubString(req_body, req_size), LogFieldOption::XORANDB64); if (res_size) log << LogField("httpResponseBody", getSubString(res_body, res_size), LogFieldOption::XORANDB64); return false; } bool SignatureAndAction::isMatchedPrevent(const Buffer &context_buffer, const set &pattern) const { if (signature->getMatch(pattern) != MatchType::MATCH) { dbgTrace(D_IPS) << "Signature doesn't match"; return false; } if (signature->isSilent()) return matchSilent(context_buffer); auto table = Singleton::Consume::by(); auto &ips_state = table->getState(); auto override_action = getAction(ips_state); MatchEvent(signature, get<0>(override_action)).notify(); if (get<0>(override_action) == IPSSignatureSubTypes::SignatureAction::IGNORE) { dbgDebug(D_IPS) << "Ignored signature"; return false; } dbgDebug(D_IPS) << "Signature matched - sending log"; auto trigger = getTrigger(); bool is_prevent = get<0>(override_action) == IPSSignatureSubTypes::SignatureAction::PREVENT; auto severity = signature->getSeverity() < IPSLevel::HIGH ? Severity::HIGH : Severity::CRITICAL; if (get<0>(override_action) == IPSSignatureSubTypes::SignatureAction::DETECT) severity = Severity::INFO; LogGen log = trigger( "Web Request", LogTriggerConf::SecurityType::ThreatPrevention, severity, Priority::HIGH, is_prevent, LogField("practiceType", "Threat Prevention"), Tags::IPS ); log << LogField("matchedSignatureConfidence", signature->getConfidenceString()) << LogField("matchedSignaturePerformance", signature->getPerformanceString()) << LogField("matchedSignatureSeverity", signature->getSeverityString()) << LogField("matchedSignatureCVE", makeSeparatedStr(signature->getCveList(), ", ")) << LogField("signatureVersion", signature->getUpdateVersion()) << LogField("protectionId", signature->getName()) << LogField("indicatorsSource", signature->getSource()) << LogField("indicatorsVersion", signature->getFeedVersion()) << LogField("waapIncidentType", signature->getIncidentType()); if (context_buffer.size() < 1024) { log << LogField("matchedSample", static_cast(context_buffer), LogFieldOption::XORANDB64); } else { auto sample = context_buffer; sample.keepHead(1024); log << LogField("matchedSample", static_cast(sample), LogFieldOption::XORANDB64); } auto year = signature->getYear(); if (year.ok()) log << LogField("matchedSignatureYear", to_string(*year)); auto env = Singleton::Consume::by(); auto host = env->get(HttpTransactionData::host_name_ctx); if (host.ok()) log << LogField("httpHostName", host.unpack()); auto client_ip = env->get(HttpTransactionData::client_ip_ctx); if (client_ip.ok()) { stringstream client_ip_str; client_ip_str << client_ip.unpack(); log << LogField("sourceIP", client_ip_str.str()); } auto proxy_ip = env->get(HttpTransactionData::proxy_ip_ctx); if (proxy_ip.ok()) { log << LogField("proxyIP", static_cast(proxy_ip.unpack())); } auto source_identifier = env->get(HttpTransactionData::source_identifier); if (source_identifier.ok()) { log << LogField("httpSourceId", static_cast(source_identifier.unpack())); } auto req_header = ips_state.getTransactionData(IPSCommonTypes::requests_header_for_log); if (req_header.ok() && trigger.isWebLogFieldActive(headers)) { log << LogField("httpRequestHeaders", static_cast(req_header.unpack()), LogFieldOption::XORANDB64); } auto client_port = env->get(HttpTransactionData::client_port_ctx); if (client_port.ok()) log << LogField("sourcePort", client_port.unpack()); auto method = env->get(HttpTransactionData::method_ctx); if (method.ok()) log << LogField("httpMethod", method.unpack()); uint max_size = getConfigurationWithDefault(1536, "IPS", "Max Field Size"); if (trigger.isWebLogFieldActive(url_path)) { auto path = env->get("HTTP_PATH_DECODED"); if (path.ok()) { log << LogField("httpUriPath", getSubString(path, max_size), LogFieldOption::XORANDB64); } else { auto transaction_path = env->get(HttpTransactionData::uri_path_decoded); if (transaction_path.ok()) { auto uri_path = transaction_path.unpack(); auto question_mark = uri_path.find('?'); log << LogField("httpUriPath", uri_path.substr(0, question_mark), LogFieldOption::XORANDB64); } } } if (trigger.isWebLogFieldActive(url_query)) { auto query = env->get("HTTP_QUERY_DECODED"); if (query.ok()) { log << LogField("httpUriQuery", getSubString(query, max_size), LogFieldOption::XORANDB64); } else { auto transaction_query = env->get(HttpTransactionData::uri_query_decoded); if (transaction_query.ok()) { log << LogField("httpUriQuery", transaction_query.unpack()); } } } auto res_code = env->get("HTTP_RESPONSE_CODE"); if (res_code.ok() && trigger.isWebLogFieldActive(::res_code)) { log << LogField("httpResponseCode", static_cast(res_code.unpack())); } auto req_body = env->get("HTTP_REQUEST_BODY"); auto res_body = env->get("HTTP_RESPONSE_BODY"); uint req_size = req_body.ok() && trigger.isWebLogFieldActive(::req_body) ? req_body.unpack().size() : 0; uint res_size = res_body.ok() && trigger.isWebLogFieldActive(::res_body) ? res_body.unpack().size() : 0; if (req_size + res_size > max_size) { if (req_size + 500 > max_size) { res_size = std::min(500u, res_size); req_size = max_size - res_size; } else { res_size = max_size - req_size; } } if (req_size) log << LogField("httpRequestBody", getSubString(req_body, req_size), LogFieldOption::XORANDB64); if (res_size) log << LogField("httpResponseBody", getSubString(res_body, res_size), LogFieldOption::XORANDB64); log << LogField("waapOverride", get<1>(override_action)); if (!get<2>(override_action).empty()) log.addToOrigin(LogField("exceptionIdList", get<2>(override_action))); log << LogField("securityAction", is_prevent ? "Prevent" : "Detect"); return is_prevent; } void IPSSignaturesResource::load(cereal::JSONInputArchive &ar) { if (!IPSHelper::hasDeobfuscation()) return; vector sigs; cereal::load(ar, sigs); all_signatures.reserve(sigs.size()); for (auto &sig : sigs) { if (sig.isOk()) { all_signatures.emplace_back(make_shared(move(sig))); } } } class CompleteSignatureWrapper { public: void load(cereal::JSONInputArchive &ar) { try { sig.load(ar); is_loaded = true; } catch (const cereal::Exception &e) { ar.finishNode(); reportError(e.what()); } catch (const Config::ConfigException &e) { ar.finishNode(); reportError(e.getError()); } } bool isOk() const { return is_loaded; } void setIndicators(const string &source, const string &version) { sig.setIndicators(source, version); } shared_ptr getPtr() { return make_shared(move(sig)); } private: void reportError(const string &err) { dbgError(D_IPS) << "Failed to load signature due to: " << err; if (sig.getName() != "") { string remediation = "Verify the validity of the '" + sig.getName() + "' signature."; LogGen( "Could not load a Snort signature from configured file", ReportIS::Level::ACTION, ReportIS::Audience::SECURITY, ReportIS::Severity::CRITICAL, ReportIS::Priority::URGENT, LogField("EventTopic", "Snort Signatures"), ReportIS::Tags::POLICY_INSTALLATION ) << LogField("EventRemediation", remediation); } } CompleteSignature sig; bool is_loaded = false; }; void SnortSignaturesResourceFile::load(cereal::JSONInputArchive &ar) { string time; vector sigs; ar( cereal::make_nvp("modificationTime", time), cereal::make_nvp("name", name), cereal::make_nvp("protections", sigs) ); all_signatures.reserve(sigs.size()); for (auto &sig : sigs) { if (sig.isOk()) { sig.setIndicators(name, time); all_signatures.emplace_back(sig.getPtr()); } } } void SnortSignaturesResource::load(cereal::JSONInputArchive &ar) { cereal::load(ar, files); } void IPSSignaturesPerContext::addSignature(const IPSSignatureSubTypes::SignatureAndAction &sig) { auto patterns = sig.patternsInSignature(); if (patterns.empty()) { signatures_without_lss.push_back(sig); return; } for (auto &pat : patterns) { signatures_per_lss[pat].push_back(sig); } } void IPSSignaturesPerContext::calcFirstTier(const string &ctx_name) { std::set patterns; for (const auto &lss_to_sig : signatures_per_lss) { patterns.emplace(lss_to_sig.first); } first_tier = Singleton::Consume::by()->getHook(ctx_name, patterns); } set IPSSignaturesPerContext::getFirstTierMatches(const Buffer &buffer) const { return first_tier->ok() ? first_tier->scanBuf(buffer) : set(); } bool IPSSignaturesPerContext::isMatchedPrevent(const Buffer &context_buffer) const { auto first_tier_res = getFirstTierMatches(context_buffer); for (auto &pat : first_tier_res) { auto find = signatures_per_lss.find(pat); if (find == signatures_per_lss.end()) continue; for (auto &sig : find->second) { if (sig.isMatchedPrevent(context_buffer, first_tier_res)) return true; } } for (auto &sig : signatures_without_lss) { if (sig.isMatchedPrevent(context_buffer, first_tier_res)) return true; } return false; } void IPSSignatures::load(cereal::JSONInputArchive &ar) { ar( cereal::make_nvp("assetName", asset_name), cereal::make_nvp("practiceName", practice_name) ); try { ar(cereal::make_nvp("assetId", asset_id)); } catch (const cereal::Exception &e) { ar.setNextName(nullptr); asset_id = ""; } try { ar(cereal::make_nvp("practiceId", practice_id)); } catch (const cereal::Exception &e) { ar.setNextName(nullptr); practice_id = ""; } try { ar(cereal::make_nvp("sourceIdentifier", source_id)); for (auto &ch : source_id) { ch = tolower(ch); } } catch (const cereal::Exception &e) { ar.setNextName(nullptr); source_id = ""; } RuleSelector ruleSelector; ruleSelector.load(ar); std::vector signatures = ruleSelector.selectSignatures(); if (signatures.empty()) { dbgDebug(D_IPS) << "[IPS] Could not find any match between rules and signatures."; return; } for (const auto &sig : signatures) { auto &sig_contexts = sig.getContext(); for (auto &sig_context : sig_contexts) { signatures_per_context[sig_context].addSignature(sig); } } for (auto &sig_per_ctx : signatures_per_context) { sig_per_ctx.second.calcFirstTier(sig_per_ctx.first); } } bool IPSSignatures::isMatchedPrevent(const string &context_name, const Buffer &context_buffer) const { auto curr_sig = signatures_per_context.find(context_name); if (curr_sig == signatures_per_context.end()) { dbgDebug(D_IPS) << "[IPS] No signatures for " << context_name; return false; } auto &config = getConfiguration("IPS", "IpsProtections"); ScopedContext ctx; auto SOURCE = EnvKeyAttr::LogSection::SOURCE; if (config.ok()) { ctx.registerValue("practiceName", (*config).getPractice(), SOURCE); ctx.registerValue("practiceId", (*config).getPracticeId(), SOURCE); } ctx.registerValue("practiceSubType", "Web IPS", SOURCE); auto is_matched = curr_sig->second.isMatchedPrevent(context_buffer); return is_matched; } bool IPSSignatures::isEmpty(const std::string &context) const { return signatures_per_context.find(context) == signatures_per_context.end(); } void SnortSignatures::load(cereal::JSONInputArchive &ar) { ar( cereal::make_nvp("assetName", asset_name), cereal::make_nvp("practiceName", practice_name) ); try { ar(cereal::make_nvp("assetId", asset_id)); } catch (const cereal::Exception &e) { ar.setNextName(nullptr); asset_id = ""; } try { ar(cereal::make_nvp("practiceId", practice_id)); } catch (const cereal::Exception &e) { ar.setNextName(nullptr); practice_id = ""; } try { ar(cereal::make_nvp("sourceIdentifier", source_id)); for (auto &ch : source_id) { ch = tolower(ch); } } catch (const cereal::Exception &e) { ar.setNextName(nullptr); source_id = ""; } SnortRuleSelector ruleSelector; ruleSelector.load(ar); std::vector signatures = ruleSelector.selectSignatures(); if (signatures.empty()) { dbgDebug(D_IPS) << "[Snort] Could not find any match between rules and signatures."; return; } for (const auto &sig : signatures) { auto &sig_contexts = sig.getContext(); for (auto &sig_context : sig_contexts) { signatures_per_context[sig_context].addSignature(sig); } } for (auto &sig_per_ctx: signatures_per_context) { sig_per_ctx.second.calcFirstTier(sig_per_ctx.first); } } bool SnortSignatures::isMatchedPrevent(const string &context_name, const Buffer &context_buffer) const { auto curr_sig = signatures_per_context.find(context_name); if (curr_sig == signatures_per_context.end()) { dbgDebug(D_IPS) << "[Snort] No signatures for " << context_name; return false; } auto &config = getConfiguration("IPSSnortSigs", "SnortProtections"); ScopedContext ctx; auto SOURCE = EnvKeyAttr::LogSection::SOURCE; if (config.ok()) { ctx.registerValue("assetName", (*config).getAsset(), SOURCE); ctx.registerValue("assetId", (*config).getAssetId(), SOURCE); ctx.registerValue("practiceName", (*config).getPractice(), SOURCE); ctx.registerValue("practiceId", (*config).getPracticeId(), SOURCE); } ctx.registerValue("practiceSubType", "Web Snort", SOURCE); auto is_matched = curr_sig->second.isMatchedPrevent(context_buffer); return is_matched; } bool SnortSignatures::isEmpty(const std::string &context) const { return signatures_per_context.find(context) == signatures_per_context.end(); }