From 554251bade3a5074446c98dc044e2cb383d9dbf8 Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Fri, 28 Sep 2018 10:28:02 -0300 Subject: [PATCH] Refactoring on the Rule class --- headers/modsecurity/rule.h | 72 +- src/operators/detect_sqli.cc | 3 +- src/operators/detect_xss.cc | 3 +- src/operators/pm.cc | 4 +- src/operators/rbl.cc | 3 +- src/operators/rx.cc | 3 +- src/operators/verify_cc.cc | 3 +- src/operators/verify_cpf.cc | 3 +- src/operators/verify_ssn.cc | 3 +- src/parser/driver.cc | 4 +- src/rule.cc | 965 +++++++----------- src/variables/variable.h | 10 + .../action-ctl_rule_remove_target_by_id.json | 9 +- .../action-ctl_rule_remove_target_by_tag.json | 5 +- .../config-update-target-by-id.json | 4 +- .../config-update-target-by-msg.json | 5 +- .../config-update-target-by-tag.json | 5 +- 17 files changed, 474 insertions(+), 630 deletions(-) diff --git a/headers/modsecurity/rule.h b/headers/modsecurity/rule.h index 7e5f9764..c51fc815 100644 --- a/headers/modsecurity/rule.h +++ b/headers/modsecurity/rule.h @@ -38,6 +38,12 @@ class Variables; } namespace actions { class Action; +class Severity; +class LogData; +class Msg; +class Rev; +class SetVar; +class Tag; } namespace operators { class Operator; @@ -55,15 +61,31 @@ class Rule { virtual bool evaluate(Transaction *transaction, std::shared_ptr rm); - bool evaluateActions(Transaction *transaction); - std::vector> - getFinalVars(Transaction *trasn); + + void organizeActions(std::vector *actions); + void cleanUpActions(); + void executeAction(Transaction *trans, + bool containsBlock, std::shared_ptr ruleMessage, + actions::Action *a, bool context); + + inline void executeTransformation(actions::Action *a, + std::shared_ptr *value, + Transaction *trans, + std::list, + std::shared_ptr>> *ret, + std::string *path, + int *nth); + + void getVariablesExceptions(Transaction *t, + Variables::Variables *exclusion, Variables::Variables *addition); + inline void getFinalVars(Variables::Variables *vars, + Variables::Variables *eclusion, Transaction *trans); void executeActionsAfterFullMatch(Transaction *trasn, bool containsDisruptive, std::shared_ptr ruleMessage); std::list, std::shared_ptr>> executeDefaultTransformations( - Transaction *trasn, const std::string &value, bool multiMatch); + Transaction *trasn, const std::string &value); bool executeOperatorAt(Transaction *trasn, std::string key, std::string value, std::shared_ptr rm); @@ -72,14 +94,12 @@ class Rule { void updateMatchedVars(Transaction *trasn, std::string key, std::string value); void cleanMatchedVars(Transaction *trasn); - void updateRulesVariable(Transaction *trasn); + void updateRulesVariable(Transaction *trasn, std::shared_ptr rm); - //std::vector getActionNames(); std::vector getActionsByName(const std::string& name, Transaction *t); bool containsTag(const std::string& name, Transaction *t); bool containsMsg(const std::string& name, Transaction *t); - bool containsStaticDisruptiveAction(); int refCountDecreaseAndCheck() { m_referenceCount--; @@ -95,26 +115,48 @@ class Rule { m_referenceCount++; } + void executeTransformations( + actions::Action *a, + std::shared_ptr newValue, + std::shared_ptr value, + Transaction *trans, + std::list, + std::shared_ptr>> *ret, + std::shared_ptr transStr, + int nth); - int m_accuracy; - std::vector m_actionsConf; std::vector m_actionsRuntimePos; std::vector m_actionsRuntimePre; bool m_chained; Rule *m_chainedRule; std::string m_fileName; int m_lineNumber; - std::string m_logData; std::string m_marker; - int m_maturity; operators::Operator *m_op; - int m_phase; - std::string m_rev; - int64_t m_ruleId; bool m_secMarker; modsecurity::Variables::Variables *m_variables; - std::string m_ver; + + int64_t m_ruleId; + std::string m_rev; + // msg ? + std::string m_ver; + //std::string m_logData; + + //if (child->severity != NOT_SET) merged->severity = child->severity; + int m_accuracy; + int m_maturity; + int m_phase; + + bool m_containsStaticDisruptiveAction; + bool m_containsCaptureAction; + bool m_containsMultiMatchAction; + bool m_containsStaticBlockAction; + actions::Severity *m_severity; + actions::LogData *m_logData; + actions::Msg *m_msg; + std::vector m_actionsSetVar; + std::vector m_actionsTag; private: bool m_unconditional; int m_referenceCount; diff --git a/src/operators/detect_sqli.cc b/src/operators/detect_sqli.cc index aa8782a8..71cb4ede 100644 --- a/src/operators/detect_sqli.cc +++ b/src/operators/detect_sqli.cc @@ -40,8 +40,7 @@ bool DetectSQLi::evaluate(Transaction *t, Rule *rule, "fingerprint '" + std::string(fingerprint) + "' at: '" + input + "'"); #endif - if (rule && t - && rule->getActionsByName("capture", t).size() > 0) { + if (rule && t && rule->m_containsCaptureAction) { t->m_collections.m_tx_collection->storeOrUpdateFirst( "0", std::string(fingerprint)); #ifndef NO_LOGS diff --git a/src/operators/detect_xss.cc b/src/operators/detect_xss.cc index ed0f754b..6ba54f5f 100644 --- a/src/operators/detect_xss.cc +++ b/src/operators/detect_xss.cc @@ -36,8 +36,7 @@ bool DetectXSS::evaluate(Transaction *t, Rule *rule, #ifndef NO_LOGS t->debug(5, "detected XSS using libinjection."); #endif - if (rule && t - && rule->getActionsByName("capture", t).size() > 0) { + if (rule && t && rule->m_containsCaptureAction) { t->m_collections.m_tx_collection->storeOrUpdateFirst( "0", std::string(input)); #ifndef NO_LOGS diff --git a/src/operators/pm.cc b/src/operators/pm.cc index b2cd7410..00823d43 100644 --- a/src/operators/pm.cc +++ b/src/operators/pm.cc @@ -96,8 +96,6 @@ bool Pm::evaluate(Transaction *transaction, Rule *rule, #ifdef MODSEC_MUTEX_ON_PM pthread_mutex_unlock(&m_lock); #endif - bool capture = rule && rule->getActionsByName("capture", - transaction).size() > 0; if (rc > 0 && transaction) { std::string match_(match); @@ -105,7 +103,7 @@ bool Pm::evaluate(Transaction *transaction, Rule *rule, transaction->m_matched.push_back(match_); } - if (capture && transaction && rc) { + if (rule && rule->m_containsCaptureAction && transaction && rc) { transaction->m_collections.m_tx_collection->storeOrUpdateFirst("0", std::string(match)); #ifndef NO_LOGS diff --git a/src/operators/rbl.cc b/src/operators/rbl.cc index ce071935..39210af5 100644 --- a/src/operators/rbl.cc +++ b/src/operators/rbl.cc @@ -222,8 +222,7 @@ bool Rbl::evaluate(Transaction *t, Rule *rule, furtherInfo(sin, ipStr, t); freeaddrinfo(info); - if (rule && t - && rule->getActionsByName("capture", t).size() > 0) { + if (rule && t && rule->m_containsCaptureAction) { t->m_collections.m_tx_collection->storeOrUpdateFirst( "0", std::string(ipStr)); #ifndef NO_LOGS diff --git a/src/operators/rx.cc b/src/operators/rx.cc index df6d6d43..36a43693 100644 --- a/src/operators/rx.cc +++ b/src/operators/rx.cc @@ -54,8 +54,7 @@ bool Rx::evaluate(Transaction *transaction, Rule *rule, } matches = re->searchAll(input); - if (rule && rule->getActionsByName("capture", - transaction).size() > 0 && transaction) { + if (rule && rule->m_containsCaptureAction && transaction) { int i = 0; matches.reverse(); for (const SMatch& a : matches) { diff --git a/src/operators/verify_cc.cc b/src/operators/verify_cc.cc index 3d8bd4e3..e3311fe0 100644 --- a/src/operators/verify_cc.cc +++ b/src/operators/verify_cc.cc @@ -142,8 +142,7 @@ bool VerifyCC::evaluate(Transaction *t, Rule *rule, is_cc = luhnVerify(match.c_str(), match.size()); if (is_cc) { if (t) { - if (rule && t - && rule->getActionsByName("capture", t).size() > 0) { + if (rule && t && rule->m_containsCaptureAction) { t->m_collections.m_tx_collection->storeOrUpdateFirst( "0", std::string(match)); #ifndef NO_LOGS diff --git a/src/operators/verify_cpf.cc b/src/operators/verify_cpf.cc index 3f26a5a8..9c7d403c 100644 --- a/src/operators/verify_cpf.cc +++ b/src/operators/verify_cpf.cc @@ -133,8 +133,7 @@ bool VerifyCPF::evaluate(Transaction *t, Rule *rule, is_cpf = verify(i.match.c_str(), i.match.size()); if (is_cpf) { logOffset(ruleMessage, i.m_offset, i.m_length); - if (rule && t - && rule->getActionsByName("capture", t).size() > 0) { + if (rule && t && rule->m_containsCaptureAction) { t->m_collections.m_tx_collection->storeOrUpdateFirst( "0", std::string(i.match)); #ifndef NO_LOGS diff --git a/src/operators/verify_ssn.cc b/src/operators/verify_ssn.cc index 776f56df..88e7c084 100644 --- a/src/operators/verify_ssn.cc +++ b/src/operators/verify_ssn.cc @@ -124,8 +124,7 @@ bool VerifySSN::evaluate(Transaction *t, Rule *rule, is_ssn = verify(i.match.c_str(), i.match.size()); if (is_ssn) { logOffset(ruleMessage, i.m_offset, i.m_length); - if (rule && t - && rule->getActionsByName("capture", t).size() > 0) { + if (rule && t && rule->m_containsCaptureAction) { t->m_collections.m_tx_collection->storeOrUpdateFirst( "0", std::string(i.match)); #ifndef NO_LOGS diff --git a/src/parser/driver.cc b/src/parser/driver.cc index 157b4e9e..a4ee3f87 100644 --- a/src/parser/driver.cc +++ b/src/parser/driver.cc @@ -81,7 +81,7 @@ int Driver::addSecRule(Rule *rule) { if (lastRule->m_chainedRule == NULL) { rule->m_phase = lastRule->m_phase; lastRule->m_chainedRule = rule; - if (rule->containsStaticDisruptiveAction()) { + if (rule->m_containsStaticDisruptiveAction) { m_parserError << "Disruptive actions can only be specified by"; m_parserError << " chain starter rules."; return false; @@ -94,7 +94,7 @@ int Driver::addSecRule(Rule *rule) { } if (a->m_chained && a->m_chainedRule == NULL) { a->m_chainedRule = rule; - if (a->containsStaticDisruptiveAction()) { + if (a->m_containsStaticDisruptiveAction) { m_parserError << "Disruptive actions can only be "; m_parserError << "specified by chain starter rules."; return false; diff --git a/src/rule.cc b/src/rule.cc index aaa0c775..15a6401a 100644 --- a/src/rule.cc +++ b/src/rule.cc @@ -35,6 +35,10 @@ #include "src/actions/msg.h" #include "src/actions/log_data.h" #include "src/actions/severity.h" +#include "src/actions/capture.h" +#include "src/actions/multi_match.h" +#include "src/actions/set_var.h" +#include "src/actions/disruptive/block.h" #include "src/variables/variable.h" @@ -48,14 +52,14 @@ using actions::transformations::None; Rule::Rule(std::string marker) : m_accuracy(0), - m_actionsConf(), m_actionsRuntimePos(), m_actionsRuntimePre(), + m_actionsSetVar(), + m_actionsTag(), m_chained(false), m_chainedRule(NULL), m_fileName(""), m_lineNumber(0), - m_logData(""), m_marker(marker), m_maturity(0), m_op(NULL), @@ -66,23 +70,30 @@ Rule::Rule(std::string marker) m_variables(NULL), m_ver(""), m_unconditional(false), - m_referenceCount(1) { } + m_referenceCount(1), + m_containsStaticDisruptiveAction(false), + m_containsStaticBlockAction(false), + m_containsCaptureAction(false), + m_containsMultiMatchAction(false), + m_severity(nullptr), + m_logData(nullptr), + m_msg(nullptr) { } Rule::Rule(Operator *_op, - Variables::Variables *_variables, - std::vector *actions, - std::string fileName, - int lineNumber) + Variables::Variables *_variables, + std::vector *actions, + std::string fileName, + int lineNumber) : m_accuracy(0), - m_actionsConf(), m_actionsRuntimePos(), m_actionsRuntimePre(), + m_actionsSetVar(), + m_actionsTag(), m_chained(false), m_chainedRule(NULL), m_fileName(fileName), m_lineNumber(lineNumber), - m_logData(""), m_marker(""), m_maturity(0), m_op(_op), @@ -93,24 +104,17 @@ Rule::Rule(Operator *_op, m_variables(_variables), m_ver(""), m_unconditional(false), - m_referenceCount(1) { - if (actions != NULL) { - for (Action *a : *actions) { - if (a->action_kind == Action::ConfigurationKind) { - m_actionsConf.push_back(a); - a->evaluate(this, NULL); - } else if (a->action_kind - == Action::RunTimeBeforeMatchAttemptKind) { - m_actionsRuntimePre.push_back(a); - } else if (a->action_kind == Action::RunTimeOnlyIfMatchKind) { - m_actionsRuntimePos.push_back(a); - } else { - std::cout << "General failure, action: " << a->m_name; - std::cout << " has an unknown type." << std::endl; - delete a; - } - } - } + m_referenceCount(1), + m_containsStaticDisruptiveAction(false), + m_containsStaticBlockAction(false), + m_containsCaptureAction(false), + m_containsMultiMatchAction(false), + m_severity(nullptr), + m_logData(nullptr), + m_msg(nullptr) { + /* */ + organizeActions(actions); + /** * If phase is not entered, we assume phase 2. For historical reasons. * @@ -119,9 +123,7 @@ Rule::Rule(Operator *_op, m_phase = modsecurity::Phases::RequestHeadersPhase; } - if (m_op == NULL) { - m_unconditional = true; - } + m_unconditional = (m_op == NULL); delete actions; } @@ -131,21 +133,9 @@ Rule::~Rule() { if (m_op != NULL) { delete m_op; } - while (m_actionsConf.empty() == false) { - auto *a = m_actionsConf.back(); - m_actionsConf.pop_back(); - delete a; - } - while (m_actionsRuntimePre.empty() == false) { - auto *a = m_actionsRuntimePre.back(); - m_actionsRuntimePre.pop_back(); - delete a; - } - while (m_actionsRuntimePos.empty() == false) { - auto *a = m_actionsRuntimePos.back(); - m_actionsRuntimePos.pop_back(); - delete a; - } + + cleanUpActions(); + while (m_variables != NULL && m_variables->empty() == false) { auto *a = m_variables->back(); m_variables->pop_back(); @@ -161,40 +151,86 @@ Rule::~Rule() { } } -/* -std::vector Rule::getActionNames() { - std::vector a; - for (auto &z : this->m_actionsRuntimePos) { - a.push_back(z->m_name); - } - for (auto &z : this->m_actionsRuntimePre) { - a.push_back(z->m_name); - } - for (auto &z : this->m_actionsConf) { - a.push_back(z->m_name); - } - for (auto &b : - trans->m_rules->m_exceptions.m_action_pre_update_target_by_id) { - if (m_ruleId != b.first) { - continue; - } - actions::Action *z = dynamic_cast(b.second.get()); - a.push_back(z->m_name); - } - for (auto &b : - trans->m_rules->m_exceptions.m_action_pre_update_target_by_id) { - if (m_ruleId != b.first) { - continue; - } - actions::Action *z = dynamic_cast(b.second.get()); - a.push_back(z->m_name); - } - return a; -} -*/ -bool Rule::evaluateActions(Transaction *trans) { - return true; +void Rule::organizeActions(std::vector *actions) { + if (!actions) { + return; + } + for (Action *a : *actions) { + if (a->action_kind == Action::ConfigurationKind) { + a->evaluate(this, NULL); + delete a; + } else if (a->action_kind == Action::RunTimeBeforeMatchAttemptKind) { + m_actionsRuntimePre.push_back(a); + } else if (a->action_kind == Action::RunTimeOnlyIfMatchKind) { + if (dynamic_cast(a)) { + m_containsCaptureAction = true; + delete a; + } else if (dynamic_cast(a)) { + m_containsMultiMatchAction = true; + delete a; + } else if (dynamic_cast(a)) { + m_severity = dynamic_cast(a); + } else if (dynamic_cast(a)) { + m_logData = dynamic_cast(a); + } else if (dynamic_cast(a)) { + m_msg = dynamic_cast(a); + } else if (dynamic_cast(a)) { + m_actionsSetVar.push_back( + dynamic_cast(a)); + } else if (dynamic_cast(a)) { + m_actionsTag.push_back(dynamic_cast(a)); + } else if (dynamic_cast(a)) { + m_actionsRuntimePos.push_back(a); + m_containsStaticBlockAction = true; + } else if (a->isDisruptive() == true) { + m_actionsRuntimePos.push_back(a); + m_containsStaticDisruptiveAction = true; + } else { + m_actionsRuntimePos.push_back(a); + } + } else { + std::cout << "General failure, action: " << a->m_name; + std::cout << " has an unknown type." << std::endl; + delete a; + } + } +} + + +void Rule::cleanUpActions() { + if (m_severity) { + delete m_severity; + m_severity = nullptr; + } + if (m_logData) { + delete m_logData; + m_logData = nullptr; + } + if (m_msg) { + delete m_msg; + m_msg = nullptr; + } + while (m_actionsRuntimePre.empty() == false) { + auto *a = m_actionsRuntimePre.back(); + m_actionsRuntimePre.pop_back(); + delete a; + } + while (m_actionsRuntimePos.empty() == false) { + auto *a = m_actionsRuntimePos.back(); + m_actionsRuntimePos.pop_back(); + delete a; + } + while (m_actionsSetVar.empty() == false) { + auto *a = m_actionsSetVar.back(); + m_actionsSetVar.pop_back(); + delete a; + } + while (m_actionsTag.empty() == false) { + auto *a = m_actionsTag.back(); + m_actionsTag.pop_back(); + delete a; + } } @@ -222,84 +258,69 @@ void Rule::cleanMatchedVars(Transaction *trans) { } -void Rule::updateRulesVariable(Transaction *trans) { +void Rule::updateRulesVariable(Transaction *trans, + std::shared_ptr rm) { if (m_ruleId != 0) { - trans->m_variableRule.set("id", - std::to_string(m_ruleId), 0); + trans->m_variableRule.set("id", std::to_string(m_ruleId), 0); } if (m_rev.empty() == false) { - trans->m_variableRule.set("rev", - m_rev, 0); + trans->m_variableRule.set("rev", m_rev, 0); } - if (getActionsByName("msg", trans).size() > 0) { - actions::Msg *msg = dynamic_cast( - getActionsByName("msg", trans)[0]); - trans->m_variableRule.set("msg", - msg->data(trans), 0); - } - if (getActionsByName("logdata", trans).size() > 0) { - actions::LogData *data = dynamic_cast( - getActionsByName("logdata", trans)[0]); - trans->m_variableRule.set("logdata", - data->data(trans), 0); - } - if (getActionsByName("severity", trans).size() > 0) { - actions::Severity *data = dynamic_cast( - getActionsByName("severity", trans)[0]); + if (m_severity) { trans->m_variableRule.set("severity", - std::to_string(data->m_severity), 0); + std::to_string(m_severity->m_severity), 0); + } + if (m_logData) { + trans->m_variableRule.set("logdata", m_logData->data(trans), 0); + } + if (m_msg) { + trans->m_variableRule.set("msg", m_msg->data(trans), 0); } } - - - void Rule::executeActionsIndependentOfChainedRuleResult(Transaction *trans, bool *containsBlock, std::shared_ptr ruleMessage) { - for (Action *a : this->m_actionsRuntimePos) { - if (a->isDisruptive() == true) { - if (a->m_name == "block") { + + for (actions::SetVar *a : m_actionsSetVar) { #ifndef NO_LOGS - trans->debug(9, "Rule contains a `block' action"); - *containsBlock = true; + trans->debug(4, "Running [independent] (non-disruptive) " \ + "action: " + a->m_name); #endif - } - } else { - if (a->m_name == "setvar" || a->m_name == "msg" - || a->m_name == "log") { -#ifndef NO_LOGS - trans->debug(4, "Running [independent] (non-disruptive) " \ - "action: " + a->m_name); -#endif - a->evaluate(this, trans, ruleMessage); - } - } + a->evaluate(this, trans); } + for (auto &b : trans->m_rules->m_exceptions.m_action_pre_update_target_by_id) { if (m_ruleId != b.first) { continue; } actions::Action *a = dynamic_cast(b.second.get()); - if (a->isDisruptive() == true) { - if (a->m_name == "block") { + if (a->isDisruptive() == true && a->m_name == "block") { #ifndef NO_LOGS - trans->debug(9, "Rule contains a `block' action"); + trans->debug(9, "Rule contains a `block' action"); *containsBlock = true; #endif - } - } else { - if (a->m_name == "setvar" || a->m_name == "msg" - || a->m_name == "log") { + } else if (a->m_name == "setvar") { #ifndef NO_LOGS - trans->debug(4, "Running [independent] (non-disruptive) " \ - "action: " + a->m_name); + trans->debug(4, "Running [independent] (non-disruptive) " \ + "action: " + a->m_name); #endif - a->evaluate(this, trans, ruleMessage); - } + a->evaluate(this, trans, ruleMessage); } } + + if (m_severity) { + m_severity->evaluate(this, trans, ruleMessage); + } + + if (m_logData) { + m_logData->evaluate(this, trans, ruleMessage); + } + + if (m_msg) { + m_msg->evaluate(this, trans, ruleMessage); + } } @@ -339,32 +360,61 @@ bool Rule::executeOperatorAt(Transaction *trans, std::string key, } +inline void Rule::executeTransformation(actions::Action *a, + std::shared_ptr *value, + Transaction *trans, + std::list, + std::shared_ptr>> *ret, + std::string *path, + int *nth) { + + std::string *oldValue = (*value).get(); + std::string newValue = a->evaluate(*oldValue, trans); + + if (newValue != *oldValue) { + std::shared_ptr u(new std::string(newValue)); + if (m_containsMultiMatchAction) { + std::shared_ptr t(new std::string(a->m_name)); + ret->push_back(std::make_pair(u, t)); + } + *value = u; + } + + if (path->empty()) { + path->append(a->m_name); + } else { + path->append("," + a->m_name); + } + +#ifndef NO_LOGS + trans->debug(9, " T (" + \ + std::to_string(*nth) + ") " + \ + a->m_name + ": \"" + \ + utils::string::limitTo(80, newValue) +"\""); +#endif + (*nth)++; +} + + std::list, std::shared_ptr>> Rule::executeDefaultTransformations( - - Transaction *trans, const std::string &in, bool multiMatch) { + Transaction *trans, const std::string &in) { int none = 0; int transformations = 0; - + std::string path(""); std::list, std::shared_ptr>> ret; - - std::shared_ptr value = std::shared_ptr(new std::string(in)); - std::shared_ptr newValue; - std::shared_ptr transStr = - std::shared_ptr(new std::string()); - - if (multiMatch == true) { + if (m_containsMultiMatchAction == true) { ret.push_back(std::make_pair( std::shared_ptr(value), - std::shared_ptr(transStr))); + std::shared_ptr(new std::string(path)))); ret.push_back(std::make_pair( std::shared_ptr(value), - std::shared_ptr(transStr))); + std::shared_ptr(new std::string(path)))); } for (Action *a : this->m_actionsRuntimePre) { @@ -379,62 +429,19 @@ std::list, if (none == 0) { for (Action *a : trans->m_rules->m_defaultActions[this->m_phase]) { if (a->action_kind \ - == actions::Action::RunTimeBeforeMatchAttemptKind) { - newValue = std::unique_ptr( - new std::string(a->evaluate(*value, trans))); - - if (multiMatch == true) { - if (*newValue != *value) { - ret.push_back(std::make_pair( - newValue, - transStr)); - } - } - value = std::shared_ptr(newValue); - if (transStr->empty()) { - transStr->append(a->m_name); - } else { - transStr->append("," + a->m_name); - } -#ifndef NO_LOGS - trans->debug(9, "(SecDefaultAction) T (" + \ - std::to_string(transformations) + ") " + \ - a->m_name + ": \"" + \ - utils::string::limitTo(80, *value) +"\""); -#endif - - transformations++; + != actions::Action::RunTimeBeforeMatchAttemptKind) { + continue; } + + executeTransformation(a, &value, trans, &ret, &path, + &transformations); } } for (Action *a : this->m_actionsRuntimePre) { if (none == 0) { - newValue = std::shared_ptr( - new std::string(a->evaluate(*value, trans))); - - if (multiMatch == true) { - if (*value != *newValue) { - ret.push_back(std::make_pair( - newValue, - transStr)); - value = newValue; - } - } - - value = newValue; -#ifndef NO_LOGS - trans->debug(9, " T (" + \ - std::to_string(transformations) + ") " + \ - a->m_name + ": \"" + \ - utils::string::limitTo(80, *value) + "\""); -#endif - if (transStr->empty()) { - transStr->append(a->m_name); - } else { - transStr->append("," + a->m_name); - } - transformations++; + executeTransformation(a, &value, trans, &ret, &path, + &transformations); } if (a->m_isNone) { none--; @@ -459,38 +466,15 @@ std::list, } actions::Action *a = dynamic_cast(b.second.get()); if (none == 0) { - newValue = std::shared_ptr( - new std::string(a->evaluate(*value, trans))); - - if (multiMatch == true) { - if (*value != *newValue) { - ret.push_back(std::make_pair( - newValue, - transStr)); - value = newValue; - } - } - - value = newValue; -#ifndef NO_LOGS - trans->debug(9, " T (" + \ - std::to_string(transformations) + ") " + \ - a->m_name + ": \"" + \ - utils::string::limitTo(80, *value) + "\""); -#endif - if (transStr->empty()) { - transStr->append(a->m_name); - } else { - transStr->append("," + a->m_name); - } - transformations++; + executeTransformation(a, &value, trans, &ret, &path, + &transformations); } if (a->m_isNone) { none--; } } - if (multiMatch == true) { + if (m_containsMultiMatchAction == true) { // v2 checks the last entry twice. Don't know why. ret.push_back(ret.back()); @@ -501,235 +485,139 @@ std::list, #endif } else { ret.push_back(std::make_pair( - std::shared_ptr(value), - std::shared_ptr(transStr))); + value, + std::shared_ptr(new std::string(path)))); } return ret; } -std::vector> Rule::getFinalVars( - Transaction *trans) { - std::list exclusions_update_by_tag_remove; - std::list exclusions_update_by_msg_remove; - std::list exclusions_update_by_id_remove; - Variables::Variables variables; - std::vector> finalVars; - - std::copy(m_variables->begin(), m_variables->end(), - std::back_inserter(variables)); - - for (auto &a : - trans->m_rules->m_exceptions.m_variable_update_target_by_tag) { - if (containsTag(*a.first.get(), trans) == false) { +void Rule::getVariablesExceptions(Transaction *t, + Variables::Variables *exclusion, Variables::Variables *addition) { + for (auto &a : t->m_rules->m_exceptions.m_variable_update_target_by_tag) { + if (containsTag(*a.first.get(), t) == false) { continue; } - if (dynamic_cast( - a.second.get())) { - std::vector z; - a.second->evaluate(trans, this, &z); - for (auto &y : z) { - exclusions_update_by_tag_remove.push_back( - std::string(y->m_key)); - delete y; - } - exclusions_update_by_tag_remove.push_back( - std::string(a.second->m_name)); - + Variable *b = a.second.get(); + if (dynamic_cast(b)) { + exclusion->push_back( + dynamic_cast( + b)->m_base.get()); } else { - Variable *b = a.second.get(); - variables.push_back(b); + addition->push_back(b); } } - for (auto &a : - trans->m_rules->m_exceptions.m_variable_update_target_by_msg) { - if (containsMsg(*a.first.get(), trans) == false) { + for (auto &a : t->m_rules->m_exceptions.m_variable_update_target_by_msg) { + if (containsMsg(*a.first.get(), t) == false) { continue; } - if (dynamic_cast( - a.second.get())) { - std::vector z; - a.second->evaluate(trans, this, &z); - for (auto &y : z) { - exclusions_update_by_msg_remove.push_back( - std::string(y->m_key)); - delete y; - } - exclusions_update_by_msg_remove.push_back( - std::string(a.second->m_name)); - + Variable *b = a.second.get(); + if (dynamic_cast(b)) { + exclusion->push_back( + dynamic_cast( + b)->m_base.get()); } else { - Variable *b = a.second.get(); - variables.push_back(b); + addition->push_back(b); } } - for (auto &a : - trans->m_rules->m_exceptions.m_variable_update_target_by_id) { + for (auto &a : t->m_rules->m_exceptions.m_variable_update_target_by_id) { if (m_ruleId != a.first) { continue; } - if (dynamic_cast( - a.second.get())) { - std::vector z; - a.second->evaluate(trans, this, &z); - for (auto &y : z) { - exclusions_update_by_id_remove.push_back(std::string(y->m_key)); - delete y; - } - exclusions_update_by_id_remove.push_back( - std::string(a.second->m_name)); + Variable *b = a.second.get(); + if (dynamic_cast(b)) { + exclusion->push_back( + dynamic_cast( + b)->m_base.get()); } else { - Variable *b = a.second.get(); - variables.push_back(b); + addition->push_back(b); } } - - - for (int i = 0; i < variables.size(); i++) { - Variable *variable = variables.at(i); - std::vector e; - bool ignoreVariable = false; - - variable->evaluate(trans, this, &e); - for (const VariableValue *v : e) { - std::string key = v->m_key; - - - if (std::find_if(exclusions_update_by_tag_remove.begin(), - exclusions_update_by_tag_remove.end(), - [key](std::string m) -> bool { return key == m; }) - != exclusions_update_by_tag_remove.end()) { -#ifndef NO_LOGS - trans->debug(9, "Variable: " + key + - " is part of the exclusion list (from update by tag" + - "), skipping..."); -#endif - delete v; - v = NULL; - continue; - } - - if (std::find_if(exclusions_update_by_msg_remove.begin(), - exclusions_update_by_msg_remove.end(), - [key](std::string m) -> bool { return key == m; }) - != exclusions_update_by_msg_remove.end()) { -#ifndef NO_LOGS - trans->debug(9, "Variable: " + key + - " is part of the exclusion list (from update by msg" + - "), skipping..."); -#endif - delete v; - v = NULL; - continue; - } - - if (std::find_if(exclusions_update_by_id_remove.begin(), - exclusions_update_by_id_remove.end(), - [key](std::string m) -> bool { return key == m; }) - != exclusions_update_by_id_remove.end()) { -#ifndef NO_LOGS - trans->debug(9, "Variable: " + key + - " is part of the exclusion list (from " \ - "update by ID), skipping..."); -#endif - delete v; - v = NULL; - continue; - } - - - for (auto &i : trans->m_ruleRemoveTargetByTag) { - std::string tag = i.first; - std::string args = i.second; - size_t posa = key.find(":"); - - if (containsTag(tag, trans) == false) { - continue; - } - - if (args == key) { -#ifndef NO_LOGS - trans->debug(9, "Variable: " + key + - " was excluded by ruleRemoteTargetByTag..."); -#endif - ignoreVariable = true; - break; - } - if (posa != std::string::npos) { - std::string var = std::string(key, posa); - if (var == args) { -#ifndef NO_LOGS - trans->debug(9, "Variable: " + key + - " was excluded by ruleRemoteTargetByTag..."); -#endif - ignoreVariable = true; - break; - } - } - } - - - if (ignoreVariable) { - delete v; - v = NULL; - continue; - } - - - for (auto &i : trans->m_ruleRemoveTargetById) { - int id = i.first; - std::string args = i.second; - size_t posa = key.find(":"); - - if (m_ruleId != id) { - continue; - } - - if (args == key) { -#ifndef NO_LOGS - trans->debug(9, "Variable: " + key + - " was excluded by ruleRemoveTargetById..."); -#endif - ignoreVariable = true; - break; - } - if (posa != std::string::npos) { - if (key.size() > posa) { - std::string var = std::string(key, 0, posa); - if (var == args) { -#ifndef NO_LOGS - trans->debug(9, "Variable: " + var + - " was excluded by ruleRemoveTargetById..."); -#endif - ignoreVariable = true; - break; - } - } - } - } - - - if (ignoreVariable) { - delete v; - v = NULL; - continue; - } - - std::unique_ptr var( - new VariableValue(v)); - delete v; - v = NULL; - finalVars.push_back(std::move(var)); - } - } - - return finalVars; } +inline void Rule::getFinalVars(Variables::Variables *vars, + Variables::Variables *exclusion, Transaction *trans) { + Variables::Variables addition; + + getVariablesExceptions(trans, exclusion, &addition); + + for (int i = 0; i < m_variables->size(); i++) { + Variable *variable = m_variables->at(i); + std::vector e; + + + if (exclusion->contains(variable)) { + continue; + } + if (std::find_if(trans->m_ruleRemoveTargetById.begin(), + trans->m_ruleRemoveTargetById.end(), + [&, variable, this](std::pair &m) -> bool { + return m.first == m_ruleId + && m.second == *variable->m_fullName.get(); + }) != trans->m_ruleRemoveTargetById.end()) { + continue; + } + if (std::find_if(trans->m_ruleRemoveTargetByTag.begin(), + trans->m_ruleRemoveTargetByTag.end(), + [&, variable, trans, this]( + std::pair &m) -> bool { + return containsTag(m.first, trans) + && m.second == *variable->m_fullName.get(); + }) != trans->m_ruleRemoveTargetByTag.end()) { + continue; + } + vars->push_back(variable); + } + + for (int i = 0; i < addition.size(); i++) { + Variable *variable = addition.at(i); + vars->push_back(variable); + } +} + + + +void Rule::executeAction(Transaction *trans, + bool containsBlock, std::shared_ptr ruleMessage, + Action *a, bool defaultContext) { + if (a->isDisruptive() == false) { +#ifndef NO_LOGS + trans->debug(9, "Running " \ + "action: " + a->m_name); +#endif + a->evaluate(this, trans, ruleMessage); + return; + } + + if (defaultContext && !containsBlock) { +#ifndef NO_LOGS + trans->debug(4, "Ignoring action: " + a->m_name + \ + " (rule does not cotains block)"); +#endif + return; + } + + if (trans->getRuleEngineState() == Rules::EnabledRuleEngine) { +#ifndef NO_LOGS + trans->debug(4, "Running (disruptive) action: " + a->m_name + \ + "."); +#endif + a->evaluate(this, trans, ruleMessage); + return; + } + +#ifndef NO_LOGS + trans->debug(4, "Not running disruptive action: " \ + + a->m_name + ". SecRuleEngine is not On."); +#endif +} + + + void Rule::executeActionsAfterFullMatch(Transaction *trans, bool containsBlock, std::shared_ptr ruleMessage) { @@ -737,96 +625,27 @@ void Rule::executeActionsAfterFullMatch(Transaction *trans, if (a->action_kind != actions::Action::RunTimeOnlyIfMatchKind) { continue; } + executeAction(trans, containsBlock, ruleMessage, a, true); + } - if (a->isDisruptive() == false) { + for (actions::Tag *a : this->m_actionsTag) { #ifndef NO_LOGS - trans->debug(9, "(SecDefaultAction) Running " \ - "action: " + a->m_name); -#endif - a->evaluate(this, trans, ruleMessage); - continue; - } - - if (!containsBlock) { -#ifndef NO_LOGS - trans->debug(4, "(SecDefaultAction) ignoring " \ - "action: " + a->m_name + \ - " (rule does not cotains block)"); -#endif - continue; - } - - if (trans->getRuleEngineState() == Rules::EnabledRuleEngine) { -#ifndef NO_LOGS - trans->debug(4, "(SecDefaultAction) " \ - "Running action: " + a->m_name + \ - "."); -#endif - a->evaluate(this, trans, ruleMessage); - continue; - } - -#ifndef NO_LOGS - trans->debug(4, "(SecDefaultAction) Not running action: " \ - + a->m_name + ". Rule contains 'block',"\ - + " but SecRuleEngine is not On."); + trans->debug(4, "Running (non-disruptive) action: " \ + + a->m_name); #endif + a->evaluate(this, trans, ruleMessage); } for (Action *a : this->m_actionsRuntimePos) { - if (a->isDisruptive() == false) { - if (a->m_name != "setvar" && a->m_name != "log" - && a->m_name != "msg") { -#ifndef NO_LOGS - trans->debug(4, "Running (non-disruptive) action: " \ - + a->m_name); -#endif - a->evaluate(this, trans, ruleMessage); - } - continue; - } - if (trans->getRuleEngineState() == Rules::EnabledRuleEngine) { -#ifndef NO_LOGS - trans->debug(4, "Running (disruptive) action: " + a->m_name); -#endif - a->evaluate(this, trans, ruleMessage); - continue; - } - -#ifndef NO_LOGS - trans->debug(4, "Not running disruptive action: " + \ - a->m_name + ". SecRuleEngine is not On"); -#endif + executeAction(trans, containsBlock, ruleMessage, a, false); } for (auto &b : - trans->m_rules->m_exceptions.m_action_pre_update_target_by_id) { + trans->m_rules->m_exceptions.m_action_pos_update_target_by_id) { if (m_ruleId != b.first) { continue; } actions::Action *a = dynamic_cast(b.second.get()); - if (a->isDisruptive() == false) { - if (a->m_name != "setvar" && a->m_name != "log" - && a->m_name != "msg") { -#ifndef NO_LOGS - trans->debug(4, "Running (non-disruptive) action: " \ - + a->m_name); -#endif - a->evaluate(this, trans, ruleMessage); - } - continue; - } - if (trans->getRuleEngineState() == Rules::EnabledRuleEngine) { -#ifndef NO_LOGS - trans->debug(4, "Running (disruptive) action: " + a->m_name); -#endif - a->evaluate(this, trans, ruleMessage); - continue; - } - -#ifndef NO_LOGS - trans->debug(4, "Not running disruptive action: " + \ - a->m_name + ". SecRuleEngine is not On"); -#endif + executeAction(trans, containsBlock, ruleMessage, a, false); } } @@ -836,9 +655,12 @@ bool Rule::evaluate(Transaction *trans, bool globalRet = false; Variables::Variables *variables = this->m_variables; bool recursiveGlobalRet; - bool containsBlock = false; + bool containsBlock = m_containsStaticBlockAction; std::vector> finalVars; std::string eparam; + Variables::Variables vars; + vars.reserve(4); + Variables::Variables exclusion; if (ruleMessage == NULL) { ruleMessage = std::shared_ptr( @@ -850,6 +672,7 @@ bool Rule::evaluate(Transaction *trans, if (m_secMarker == true) { return true; } + if (m_unconditional == true) { #ifndef NO_LOGS trans->debug(4, "(Rule: " + std::to_string(m_ruleId) \ @@ -897,40 +720,69 @@ bool Rule::evaluate(Transaction *trans, #endif } - updateRulesVariable(trans); + updateRulesVariable(trans, ruleMessage); - finalVars = getFinalVars(trans); + getFinalVars(&vars, &exclusion, trans); - for (auto &v : finalVars) { - const std::string value = v->m_value; - const std::string key = v->m_key; + for (auto &var : vars) { + std::vector e; + var->evaluate(trans, this, &e); + for (const VariableValue *v : e) { + const std::string &value = v->m_value; + const std::string &key = v->m_key; - std::list, - std::shared_ptr>> values; - - bool multiMatch = getActionsByName("multimatch", trans).size() > 0; - - values = executeDefaultTransformations(trans, value, - multiMatch); - for (const auto &valueTemp : values) { - bool ret; - std::string valueAfterTrans = std::move(*valueTemp.first); - - ret = executeOperatorAt(trans, key, valueAfterTrans, ruleMessage); - - if (ret == true) { - ruleMessage->m_match = m_op->resolveMatchMessage(trans, - key, value); - for (auto &i : v->m_orign) { - ruleMessage->m_reference.append(i->toText()); - } - ruleMessage->m_reference.append(*valueTemp.second); - updateMatchedVars(trans, key, value); - executeActionsIndependentOfChainedRuleResult(trans, - &containsBlock, ruleMessage); - globalRet = true; + if (exclusion.contains(v->m_key) || + std::find_if(trans->m_ruleRemoveTargetById.begin(), + trans->m_ruleRemoveTargetById.end(), + [&, v, this](std::pair &m) -> bool { + return m.first == m_ruleId && m.second == v->m_key; + }) != trans->m_ruleRemoveTargetById.end() + ) { + delete v; + v = NULL; + continue; } + if (exclusion.contains(v->m_key) || + std::find_if(trans->m_ruleRemoveTargetByTag.begin(), + trans->m_ruleRemoveTargetByTag.end(), + [&, v, trans, this](std::pair &m) -> bool { + return containsTag(m.first, trans) && m.second == v->m_key; + }) != trans->m_ruleRemoveTargetByTag.end() + ) { + delete v; + v = NULL; + continue; + } + + std::list, + std::shared_ptr>> values; + + values = executeDefaultTransformations(trans, value); + + for (const auto &valueTemp : values) { + bool ret; + std::string valueAfterTrans = std::move(*valueTemp.first); + + ret = executeOperatorAt(trans, key, valueAfterTrans, ruleMessage); + + if (ret == true) { + ruleMessage->m_match = m_op->resolveMatchMessage(trans, + key, value); + for (auto &i : v->m_orign) { + ruleMessage->m_reference.append(i->toText()); + } + ruleMessage->m_reference.append(*valueTemp.second); + updateMatchedVars(trans, key, value); + executeActionsIndependentOfChainedRuleResult(trans, + &containsBlock, ruleMessage); + globalRet = true; + } + } + delete v; + v = NULL; } + e.clear(); + e.reserve(4); } if (globalRet == false) { @@ -980,27 +832,6 @@ end_exec: } -bool Rule::containsStaticDisruptiveAction() { - for (Action *a : m_actionsRuntimePos) { - if (a->isDisruptive() == true) { - return true; - } - } - for (Action *a : m_actionsRuntimePre) { - if (a->isDisruptive() == true) { - return true; - } - } - for (Action *a : m_actionsConf) { - if (a->isDisruptive() == true) { - return true; - } - } - return false; -} - - - std::vector Rule::getActionsByName(const std::string& name, Transaction *trans) { std::vector ret; @@ -1014,11 +845,6 @@ std::vector Rule::getActionsByName(const std::string& name, ret.push_back(z); } } - for (auto &z : m_actionsConf) { - if (z->m_name == name) { - ret.push_back(z); - } - } for (auto &b : trans->m_rules->m_exceptions.m_action_pre_update_target_by_id) { if (m_ruleId != b.first) { @@ -1044,19 +870,7 @@ std::vector Rule::getActionsByName(const std::string& name, bool Rule::containsTag(const std::string& name, Transaction *t) { - for (auto &z : this->m_actionsRuntimePos) { - actions::Tag *tag = dynamic_cast (z); - if (tag != NULL && tag->getName(t) == name) { - return true; - } - } - for (auto &b : - t->m_rules->m_exceptions.m_action_pos_update_target_by_id) { - if (m_ruleId != b.first) { - continue; - } - actions::Action *a = dynamic_cast(b.second.get()); - actions::Tag *tag = dynamic_cast (a); + for (auto &tag : m_actionsTag) { if (tag != NULL && tag->getName(t) == name) { return true; } @@ -1066,24 +880,7 @@ bool Rule::containsTag(const std::string& name, Transaction *t) { bool Rule::containsMsg(const std::string& name, Transaction *t) { - for (auto &z : this->m_actionsRuntimePos) { - actions::Msg *msg = dynamic_cast (z); - if (msg != NULL && msg->data(t) == name) { - return true; - } - } - for (auto &b : - t->m_rules->m_exceptions.m_action_pos_update_target_by_id) { - if (m_ruleId != b.first) { - continue; - } - actions::Action *a = dynamic_cast(b.second.get()); - actions::Msg *msg = dynamic_cast (a); - if (msg != NULL && msg->data(t) == name) { - return true; - } - } - return false; + return m_msg && m_msg->data(t) == name; } diff --git a/src/variables/variable.h b/src/variables/variable.h index 091d0548..3c0aaee2 100644 --- a/src/variables/variable.h +++ b/src/variables/variable.h @@ -605,6 +605,16 @@ class VariableRegex : public Variable { class Variables : public std::vector { public: + bool contains(Variable *v) { + return std::find_if(begin(), end(), + [v](Variable *m) -> bool { return *v == *m; }) != end(); + }; + bool contains(const std::string &v) { + return std::find_if(begin(), end(), + [v](Variable *m) -> bool { + return v == *m->m_fullName.get(); + }) != end(); + }; }; diff --git a/test/test-cases/regression/action-ctl_rule_remove_target_by_id.json b/test/test-cases/regression/action-ctl_rule_remove_target_by_id.json index 7cba0d54..142ac623 100644 --- a/test/test-cases/regression/action-ctl_rule_remove_target_by_id.json +++ b/test/test-cases/regression/action-ctl_rule_remove_target_by_id.json @@ -4,7 +4,7 @@ "version_min":300000, "title":"Testing CtlRuleRemoveTargetById (1)", "expected":{ - "debug_log": "Variable: ARGS:pwd was excluded by ruleRemoveTargetById..." + "http_code": 200 }, "client":{ "ip":"200.249.12.31", @@ -27,8 +27,9 @@ "port":80 }, "rules":[ + "SecRuleEngine On", "SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:9002100,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=1;ARGS:pwd\"", - "SecRule ARGS \"@contais whe\" \"id:1,phase:3,t:none,nolog,pass,tag:'CRS'\"" + "SecRule ARGS \"@contains lhebs\" \"id:1,phase:3,t:none,status:202,block,deny,tag:'CRS'\"" ] }, { @@ -68,7 +69,7 @@ "version_min":300000, "title":"Testing CtlRuleRemoveTargetById (3)", "expected":{ - "debug_log": "Variable: ARGS was excluded by ruleRemoveTargetById..." + "http_code": 200 }, "client":{ "ip":"200.249.12.31", @@ -92,7 +93,7 @@ }, "rules":[ "SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:9002100,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=1;ARGS\"", - "SecRule ARGS \"@contais whe\" \"id:1,phase:3,t:none,nolog,pass,tag:'CRS'\"" + "SecRule ARGS \"@contains lhebs\" \"id:1,phase:3,t:none,status:202,block,deny,tag:'CRS'\"" ] } ] diff --git a/test/test-cases/regression/action-ctl_rule_remove_target_by_tag.json b/test/test-cases/regression/action-ctl_rule_remove_target_by_tag.json index efc82ae5..027a078d 100644 --- a/test/test-cases/regression/action-ctl_rule_remove_target_by_tag.json +++ b/test/test-cases/regression/action-ctl_rule_remove_target_by_tag.json @@ -4,7 +4,7 @@ "version_min":300000, "title":"Testing CtlRuleRemoteTargetByTag (1)", "expected":{ - "debug_log": "Variable: ARGS:pwd was excluded by ruleRemoteTargetByTag..." + "http_code": 200 }, "client":{ "ip":"200.249.12.31", @@ -27,8 +27,9 @@ "port":80 }, "rules":[ + "SecRuleEngine On", "SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:9002100,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetByTag=CRS;ARGS:pwd\"", - "SecRule ARGS \"@contais whe\" \"id:1,phase:3,t:none,nolog,pass,tag:'CRS'\"" + "SecRule ARGS \"@contains lhebs\" \"id:1,phase:3,t:none,nolog,pass,tag:'CRS',deny\"" ] }, { diff --git a/test/test-cases/regression/config-update-target-by-id.json b/test/test-cases/regression/config-update-target-by-id.json index 0a2e5ca8..143066d2 100644 --- a/test/test-cases/regression/config-update-target-by-id.json +++ b/test/test-cases/regression/config-update-target-by-id.json @@ -31,11 +31,11 @@ ] }, "expected":{ - "debug_log":"ARGS:key is part of the exclusion list \\(from update by ID\\), skipping" + "http_code": 200 }, "rules":[ "SecRuleUpdateTargetById 1 !ARGS", - "SecRule ARGS \"@contains test\" \"id:1,pass,t:trim,tag:'test'\"" + "SecRule ARGS \"@contains value\" \"id:1,pass,t:trim,tag:'test',deny\"" ] } ] diff --git a/test/test-cases/regression/config-update-target-by-msg.json b/test/test-cases/regression/config-update-target-by-msg.json index 670f749d..24fe343c 100644 --- a/test/test-cases/regression/config-update-target-by-msg.json +++ b/test/test-cases/regression/config-update-target-by-msg.json @@ -31,11 +31,12 @@ ] }, "expected":{ - "debug_log":"ARGS:key is part of the exclusion list \\(from update by msg\\), skipping" + "http_code": 200 }, "rules":[ + "SecRuleEngine On", "SecRuleUpdateTargetByMsg test !ARGS", - "SecRule ARGS \"@contains test\" \"id:1,pass,t:trim,msg:'test'\"" + "SecRule ARGS \"@contains value\" \"id:1,pass,t:trim,msg:'test',deny\"" ] } ] diff --git a/test/test-cases/regression/config-update-target-by-tag.json b/test/test-cases/regression/config-update-target-by-tag.json index 77d9d55b..9970f8ed 100644 --- a/test/test-cases/regression/config-update-target-by-tag.json +++ b/test/test-cases/regression/config-update-target-by-tag.json @@ -31,11 +31,12 @@ ] }, "expected":{ - "debug_log":"ARGS:key is part of the exclusion list \\(from update by tag\\), skipping" + "http_code": 200 }, "rules":[ + "SecRuleEngine On", "SecRuleUpdateTargetByTag test !ARGS", - "SecRule ARGS \"@contains test\" \"id:1,pass,t:trim,tag:'test'\"" + "SecRule ARGS \"@contains value\" \"id:1,pass,t:trim,tag:'test',deny\"" ] } ]