From 0096b177870c7381298fb4868b576b31422fe310 Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Sun, 22 Nov 2020 11:04:24 -0300 Subject: [PATCH] Using a custom VariableMatch* implementation Delay the variable name resolution till last minute. Fix one of the issues raised in #2376 --- CHANGES | 3 + .../anchored_set_variable_match_vars.h | 85 ++++++++++++ .../anchored_set_variable_match_vars_names.h | 85 ++++++++++++ .../anchored_variable_match_var_name.h | 92 ++++++++++++ headers/modsecurity/transaction.h | 15 +- src/Makefile.am | 2 + src/anchored_set_variable_match_vars.cc | 100 +++++++++++++ src/anchored_set_variable_match_vars_names.cc | 99 +++++++++++++ src/anchored_variable.cc | 2 +- src/rule_with_operator.cc | 13 +- src/rule_with_operator.h | 2 +- test/cppcheck_suppressions.txt | 2 +- .../regression/variable-MATCHED_VARS.json | 90 +++++++++++- .../variable-MATCHED_VARS_NAMES.json | 131 +++++++++++++++++- .../regression/variable-MATCHED_VAR_NAME.json | 6 +- 15 files changed, 703 insertions(+), 24 deletions(-) create mode 100644 headers/modsecurity/anchored_set_variable_match_vars.h create mode 100644 headers/modsecurity/anchored_set_variable_match_vars_names.h create mode 100644 headers/modsecurity/anchored_variable_match_var_name.h create mode 100644 src/anchored_set_variable_match_vars.cc create mode 100644 src/anchored_set_variable_match_vars_names.cc diff --git a/CHANGES b/CHANGES index f553f045..86b7b2fc 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ v3.x.y - YYYY-MMM-DD (to be released) ------------------------------------- + + - Using a custom VariableMatch* implementation + [#2428 - @zimmerle] - Avoids to cleanup GeoIp on ModSecurity destructor [#2041 - @zimmerle, @jptosso, @victorhora] - Fix memory leak of RuleMessages objects diff --git a/headers/modsecurity/anchored_set_variable_match_vars.h b/headers/modsecurity/anchored_set_variable_match_vars.h new file mode 100644 index 00000000..67554a4f --- /dev/null +++ b/headers/modsecurity/anchored_set_variable_match_vars.h @@ -0,0 +1,85 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 - 2020 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#ifdef __cplusplus +#include +#include + +#include "modsecurity/string_view.hpp" +#endif + +#include "modsecurity/variable_value.h" + + +#ifndef HEADERS_MODSECURITY_ANCHORED_SET_VARIABLE_MATCH_VARS_H_ +#define HEADERS_MODSECURITY_ANCHORED_SET_VARIABLE_MATCH_VARS_H_ + +#ifdef __cplusplus + +namespace modsecurity { +class Transaction; +namespace Utils { +class Regex; +} +namespace variables { +class KeyExclusions; +} + + +class AnchoredVariableMatchVars { + public: + explicit AnchoredVariableMatchVars(Transaction *t) + : m_name("MATCHED_VARS"), + m_transaction(t) + { } + + AnchoredVariableMatchVars(const AnchoredVariableMatchVars &a) = delete; + AnchoredVariableMatchVars &operator= (const AnchoredVariableMatchVars &a) = delete; + + void set(std::shared_ptr v) noexcept { + m_vvs.push_back(v); + } + + void unset() noexcept { + m_vvs.clear(); + } + + void resolve(VariableValues *l, + const variables::KeyExclusions &ke) const noexcept; + + void resolve(const std::string &key, + VariableValues *l) const noexcept; + + + void resolveRegularExpression(const Utils::Regex *r, + VariableValues *l, + const variables::KeyExclusions &ke) const noexcept; + + std::unique_ptr resolveFirst(const std::string &key) const noexcept; + + private: + std::vector> m_vvs; + const std::string m_name; + const Transaction *m_transaction; +}; + + +} // namespace modsecurity + +#endif + + +#endif // HEADERS_MODSECURITY_ANCHORED_SET_VARIABLE_MATCH_VARS_H_ + diff --git a/headers/modsecurity/anchored_set_variable_match_vars_names.h b/headers/modsecurity/anchored_set_variable_match_vars_names.h new file mode 100644 index 00000000..cd72a4d7 --- /dev/null +++ b/headers/modsecurity/anchored_set_variable_match_vars_names.h @@ -0,0 +1,85 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 - 2020 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#ifdef __cplusplus +#include +#include + +#include "modsecurity/string_view.hpp" +#endif + +#include "modsecurity/variable_value.h" + + +#ifndef HEADERS_MODSECURITY_ANCHORED_SET_VARIABLE_MATCH_VARS_NAMES_H_ +#define HEADERS_MODSECURITY_ANCHORED_SET_VARIABLE_MATCH_VARS_NAMES_H_ + +#ifdef __cplusplus + +namespace modsecurity { +class Transaction; +namespace Utils { +class Regex; +} +namespace variables { +class KeyExclusions; +} + + +class AnchoredVariableMatchVarsNames { + public: + explicit AnchoredVariableMatchVarsNames(Transaction *t) + : m_name("MATCHED_VARS_NAMES"), + m_transaction(t) + { } + + AnchoredVariableMatchVarsNames(const AnchoredVariableMatchVarsNames &a) = delete; + AnchoredVariableMatchVarsNames &operator= (const AnchoredVariableMatchVarsNames &a) = delete; + + void set(std::shared_ptr v) noexcept { + m_vvs.push_back(v); + } + + void unset() noexcept { + m_vvs.clear(); + } + + void resolve(VariableValues *l, + const variables::KeyExclusions &ke) const noexcept; + + void resolve(const std::string &key, + VariableValues *l) const noexcept; + + + void resolveRegularExpression(const Utils::Regex *r, + VariableValues *l, + const variables::KeyExclusions &ke) const noexcept; + + std::unique_ptr resolveFirst(const std::string &key) const noexcept; + + private: + std::vector> m_vvs; + const std::string m_name; + const Transaction *m_transaction; +}; + + +} // namespace modsecurity + +#endif + + +#endif // HEADERS_MODSECURITY_ANCHORED_SET_VARIABLE_MATCH_VARS_NAMES_H_ + diff --git a/headers/modsecurity/anchored_variable_match_var_name.h b/headers/modsecurity/anchored_variable_match_var_name.h new file mode 100644 index 00000000..3463aa37 --- /dev/null +++ b/headers/modsecurity/anchored_variable_match_var_name.h @@ -0,0 +1,92 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 - 2020 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#ifdef __cplusplus +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "modsecurity/string_view.hpp" +#endif + +#include "modsecurity/variable_value.h" + + +#ifndef HEADERS_MODSECURITY_ANCHORED_VARIABLE_NAME_H_ +#define HEADERS_MODSECURITY_ANCHORED_VARIABLE_NAME_H_ + +#ifdef __cplusplus + + +namespace modsecurity { +class Transaction; + +class AnchoredVariableMatchVarName { + public: + AnchoredVariableMatchVarName() + : m_name("MATCHED_VAR_NAME") + { } + + AnchoredVariableMatchVarName(const AnchoredVariableMatchVarName &a) = delete; + AnchoredVariableMatchVarName &operator= (const AnchoredVariableMatchVarName &a) = delete; + + void set(std::shared_ptr v) noexcept { + m_vv = v; + } + + void unset() noexcept { + m_vv = nullptr; + } + + void evaluate(VariableValues *l) const noexcept { + if (!m_vv) { + return; + } + const VariableValue *var = new VariableValue( + std::unique_ptr(new std::string(m_vv->getName())), + &m_name + ); + l->push_back(std::unique_ptr(var)); + } + + std::unique_ptr resolveFirst() const noexcept { + if (m_vv) { + return std::unique_ptr(new std::string(m_vv->getName())); + } + return std::unique_ptr(new std::string("")); + } + + private: + std::shared_ptr m_vv; + const std::string m_name; +}; + + +} // namespace modsecurity + +#endif + + +#endif // HEADERS_MODSECURITY_ANCHORED_VARIABLE_NAME_H_ diff --git a/headers/modsecurity/transaction.h b/headers/modsecurity/transaction.h index 80a38106..a1c6d912 100644 --- a/headers/modsecurity/transaction.h +++ b/headers/modsecurity/transaction.h @@ -42,6 +42,9 @@ typedef struct Rules_t RulesSet; #endif #include "modsecurity/anchored_set_variable.h" +#include "modsecurity/anchored_set_variable_match_vars_names.h" +#include "modsecurity/anchored_set_variable_match_vars.h" +#include "modsecurity/anchored_variable_match_var_name.h" #include "modsecurity/anchored_variable.h" #include "modsecurity/intervention.h" #include "modsecurity/collection/collections.h" @@ -136,7 +139,7 @@ class TransactionAnchoredVariables { m_variableFullRequestLength(t, "FULL_REQUEST_LENGTH"), m_variableInboundDataError(t, "INBOUND_DATA_ERROR"), m_variableMatchedVar(t, "MATCHED_VAR"), - m_variableMatchedVarName(t, "MATCHED_VAR_NAME"), + m_variableMatchedVarName(), m_variableMultipartBoundaryQuoted(t, "MULTIPART_BOUNDARY_QUOTED"), m_variableMultipartBoundaryWhiteSpace(t, "MULTIPART_BOUNDARY_WHITESPACE"), @@ -195,8 +198,8 @@ class TransactionAnchoredVariables { m_variableFilesTmpContent(t, "FILES_TMP_CONTENT"), m_variableMultipartFileName(t, "MULTIPART_FILENAME"), m_variableMultipartName(t, "MULTIPART_NAME"), - m_variableMatchedVarsNames(t, "MATCHED_VARS_NAMES"), - m_variableMatchedVars(t, "MATCHED_VARS"), + m_variableMatchedVarsNames(t), + m_variableMatchedVars(t), m_variableFiles(t, "FILES"), m_variableRequestCookies(t, "REQUEST_COOKIES"), m_variableRequestHeaders(t, "REQUEST_HEADERS"), @@ -220,7 +223,7 @@ class TransactionAnchoredVariables { AnchoredVariable m_variableFullRequestLength; AnchoredVariable m_variableInboundDataError; AnchoredVariable m_variableMatchedVar; - AnchoredVariable m_variableMatchedVarName; + AnchoredVariableMatchVarName m_variableMatchedVarName; AnchoredVariable m_variableMultipartBoundaryQuoted; AnchoredVariable m_variableMultipartBoundaryWhiteSpace; AnchoredVariable m_variableMultipartCrlfLFLines; @@ -276,8 +279,8 @@ class TransactionAnchoredVariables { AnchoredSetVariable m_variableFilesTmpContent; AnchoredSetVariable m_variableMultipartFileName; AnchoredSetVariable m_variableMultipartName; - AnchoredSetVariable m_variableMatchedVarsNames; - AnchoredSetVariable m_variableMatchedVars; + AnchoredVariableMatchVarsNames m_variableMatchedVarsNames; + AnchoredVariableMatchVars m_variableMatchedVars; AnchoredSetVariable m_variableFiles; AnchoredSetVariable m_variableRequestCookies; AnchoredSetVariable m_variableRequestHeaders; diff --git a/src/Makefile.am b/src/Makefile.am index 930c6e65..7d0faf23 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -272,6 +272,8 @@ libmodsecurity_la_SOURCES = \ parser/driver.cc \ transaction.cc \ anchored_set_variable.cc \ + anchored_set_variable_match_vars.cc \ + anchored_set_variable_match_vars_names.cc \ anchored_variable.cc \ audit_log/audit_log.cc \ audit_log/writer/writer.cc \ diff --git a/src/anchored_set_variable_match_vars.cc b/src/anchored_set_variable_match_vars.cc new file mode 100644 index 00000000..9db5543d --- /dev/null +++ b/src/anchored_set_variable_match_vars.cc @@ -0,0 +1,100 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 - 2020 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include +#include + +#include "modsecurity/anchored_set_variable_match_vars.h" +#include "modsecurity/modsecurity.h" +#include "modsecurity/transaction.h" +#include "src/utils/regex.h" +#include "src/variables/variable.h" + + +namespace modsecurity { + + +void AnchoredVariableMatchVars::resolve(VariableValues *l, + const variables::KeyExclusions &ke) const noexcept +{ + for (const auto& x : m_vvs) { + if (ke.toOmit(x->getName())) { + ms_dbg_a(m_transaction, 7, "Excluding key: " + x->getName() + + " from target value."); + continue; + } + const VariableValue *var = new VariableValue( + &m_name, + std::unique_ptr(new std::string(x->getName())), + std::unique_ptr(new std::string(x->getValue())) + ); + l->insert(l->begin(), std::unique_ptr(var)); + } +} + + +void AnchoredVariableMatchVars::resolve(const std::string &key, + VariableValues *l) const noexcept +{ + for (const auto& x : m_vvs) { + if (key != x->getName()) { + continue; + } + const VariableValue *var = new VariableValue( + &m_name, + std::unique_ptr(new std::string(x->getName())), + std::unique_ptr(new std::string(x->getValue())) + ); + l->insert(l->begin(), std::unique_ptr(var)); + } +} + + +void AnchoredVariableMatchVars::resolveRegularExpression(const Utils::Regex *r, + VariableValues *l, + const variables::KeyExclusions &ke) const noexcept +{ + for (const auto& x : m_vvs) { + int ret = Utils::regex_search(x->getName(), *r); + if (ret <= 0) { + continue; + } + if (ke.toOmit(x->getName())) { + ms_dbg_a(m_transaction, 7, "Excluding key: " + x->getName() + + " from target value."); + continue; + } + const VariableValue *var = new VariableValue( + &m_name, + std::unique_ptr(new std::string(x->getName())), + std::unique_ptr(new std::string(x->getValue())) + ); + l->insert(l->begin(), std::unique_ptr(var)); + } +} + + +std::unique_ptr AnchoredVariableMatchVars::resolveFirst(const std::string &key) const noexcept +{ + for (const auto& x : m_vvs) { + if (key != x->getName()) { + continue; + } + return std::unique_ptr(new std::string(x->getValue())); + } +} + + +} // namespace modsecurity diff --git a/src/anchored_set_variable_match_vars_names.cc b/src/anchored_set_variable_match_vars_names.cc new file mode 100644 index 00000000..e969312b --- /dev/null +++ b/src/anchored_set_variable_match_vars_names.cc @@ -0,0 +1,99 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 - 2020 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include + +#include "modsecurity/anchored_set_variable_match_vars_names.h" +#include "modsecurity/modsecurity.h" +#include "modsecurity/transaction.h" +#include "src/utils/regex.h" +#include "src/variables/variable.h" + + +namespace modsecurity { + + +void AnchoredVariableMatchVarsNames::resolve(VariableValues *l, + const variables::KeyExclusions &ke) const noexcept +{ + for (const auto& x : m_vvs) { + if (ke.toOmit(x->getName())) { + ms_dbg_a(m_transaction, 7, "Excluding key: " + x->getName() + + " from target value."); + continue; + } + const VariableValue *var = new VariableValue( + &m_name, + std::unique_ptr(new std::string(x->getName())), + std::unique_ptr(new std::string(x->getName())) + ); + l->insert(l->begin(), std::unique_ptr(var)); + } +} + + +void AnchoredVariableMatchVarsNames::resolve(const std::string &key, + VariableValues *l) const noexcept +{ + for (const auto& x : m_vvs) { + if (key != x->getName()) { + continue; + } + const VariableValue *var = new VariableValue( + &m_name, + std::unique_ptr(new std::string(x->getName())), + std::unique_ptr(new std::string(x->getName())) + ); + l->insert(l->begin(), std::unique_ptr(var)); + } +} + + +void AnchoredVariableMatchVarsNames::resolveRegularExpression(const Utils::Regex *r, + VariableValues *l, + const variables::KeyExclusions &ke) const noexcept +{ + for (const auto& x : m_vvs) { + int ret = Utils::regex_search(x->getName(), *r); + if (ret <= 0) { + continue; + } + if (ke.toOmit(x->getName())) { + ms_dbg_a(m_transaction, 7, "Excluding key: " + x->getName() + + " from target value."); + continue; + } + const VariableValue *var = new VariableValue( + &m_name, + std::unique_ptr(new std::string(x->getName())), + std::unique_ptr(new std::string(x->getName())) + ); + l->insert(l->begin(), std::unique_ptr(var)); + } +} + + +std::unique_ptr AnchoredVariableMatchVarsNames::resolveFirst(const std::string &key) const noexcept +{ + for (const auto& x : m_vvs) { + if (key != x->getName()) { + continue; + } + return std::unique_ptr(new std::string(x->getName())); + } +} + + +} // namespace modsecurity diff --git a/src/anchored_variable.cc b/src/anchored_variable.cc index 940714c4..6669228d 100644 --- a/src/anchored_variable.cc +++ b/src/anchored_variable.cc @@ -19,7 +19,7 @@ #include #include -#include "../headers/modsecurity/anchored_variable.h" +#include "modsecurity/anchored_variable.h" #include "modsecurity/modsecurity.h" #include "modsecurity/transaction.h" #include "src/utils/regex.h" diff --git a/src/rule_with_operator.cc b/src/rule_with_operator.cc index 9bef6d52..ddd49d06 100644 --- a/src/rule_with_operator.cc +++ b/src/rule_with_operator.cc @@ -79,17 +79,14 @@ RuleWithOperator::~RuleWithOperator() { void RuleWithOperator::updateMatchedVars(Transaction *trans, - const VariableValue *v, + std::shared_ptr v, const bpstd::string_view &value) { - // FIXME: Memory leak. - const std::string *key = new std::string(v->getName()); - ms_dbg_a(trans, 9, "Matched vars updated."); trans->m_variableMatchedVar.set(value, trans->m_variableOffset); - trans->m_variableMatchedVarName.set(*key, trans->m_variableOffset); + trans->m_variableMatchedVarName.set(v); - trans->m_variableMatchedVars.set(*key, value, trans->m_variableOffset); - trans->m_variableMatchedVarsNames.set(*key, *key, trans->m_variableOffset); + trans->m_variableMatchedVars.set(v); + trans->m_variableMatchedVarsNames.set(v); } @@ -354,7 +351,7 @@ bool RuleWithOperator::evaluate(Transaction *trans) const { iter2++; } - updateMatchedVars(trans, v, view); + updateMatchedVars(trans, vv, view); executeActionsIndependentOfChainedRuleResult(trans); globalRet = true; diff --git a/src/rule_with_operator.h b/src/rule_with_operator.h index 02d46549..097da682 100644 --- a/src/rule_with_operator.h +++ b/src/rule_with_operator.h @@ -82,7 +82,7 @@ class RuleWithOperator : public RuleWithActions { const bpstd::string_view &value) const; static void updateMatchedVars(Transaction *transaction, - const VariableValue *v, + std::shared_ptr v, const bpstd::string_view &value); static void cleanMatchedVars(Transaction *trasn); diff --git a/test/cppcheck_suppressions.txt b/test/cppcheck_suppressions.txt index 98e6bbd2..c9d3b23f 100644 --- a/test/cppcheck_suppressions.txt +++ b/test/cppcheck_suppressions.txt @@ -42,7 +42,7 @@ redundantAssignment:src/operators/pm.cc:94 functionStatic:src/operators/geo_lookup.h:39 useInitializationList:src/utils/shared_files.h:87 unmatchedSuppression:src/utils/msc_tree.cc -functionStatic:headers/modsecurity/transaction.h:438 +functionStatic:headers/modsecurity/transaction.h:441 duplicateBranch:src/audit_log/audit_log.cc:223 unreadVariable:src/request_body_processor/multipart.cc:435 stlcstrParam:src/audit_log/writer/parallel.cc:145 diff --git a/test/test-cases/regression/variable-MATCHED_VARS.json b/test/test-cases/regression/variable-MATCHED_VARS.json index 7d469a0f..ee097243 100644 --- a/test/test-cases/regression/variable-MATCHED_VARS.json +++ b/test/test-cases/regression/variable-MATCHED_VARS.json @@ -2,7 +2,7 @@ { "enabled":1, "version_min":300000, - "title":"Testing Variables :: MATCHED_VARS (1/2)", + "title":"Testing Variables :: MATCHED_VARS (1/4)", "client":{ "ip":"200.249.12.31", "port":123 @@ -43,7 +43,7 @@ { "enabled":1, "version_min":300000, - "title":"Testing Variables :: MATCHED_VARS (2/2)", + "title":"Testing Variables :: MATCHED_VARS (2/4)", "client":{ "ip":"200.249.12.31", "port":123 @@ -81,6 +81,92 @@ "SecRule MATCHED_VARS \"@contains asdf\" \"\"", "SecRule MATCHED_VARS \"@contains value\" \"id:29\"" ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: MATCHED_VARS (3/4)", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*" + }, + "uri":"/?keyI=value&keyII=other_value", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "debug_log":"Target value: \"other_value\" \\(Variable: MATCHED_VARS:ARGS:keyII\\)", + "http_code": 302, + "error_log": "whee MATCHED_VARS:ARGS:keyII test" + }, + "rules":[ + "SecRuleEngine On", + "SecRule ARGS:keyI \"@contains value\" \"chain,id:28,deny,status:302\"", + "SecRule ARGS:keyII \"@contains other_value\" \"chain\"", + "SecRule MATCHED_VARS:ARGS:keyII \"@contains other_value\" \"msg:'whee %{MATCHED_VARS_NAMES}% test'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: MATCHED_VARS (4/4)", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*" + }, + "uri":"/?keyI=value&keyII=other_value", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "debug_log":"Target value: \"other_value\" \\(Variable: MATCHED_VARS:ARGS:keyII\\)", + "http_code": 302, + "error_log": "whee MATCHED_VARS:ARGS:keyII test" + }, + "rules":[ + "SecRuleEngine On", + "SecRule ARGS:keyI \"@contains value\" \"chain,id:28,deny,status:302\"", + "SecRule ARGS:keyII \"@contains other_value\" \"chain\"", + "SecRule MATCHED_VARS:/ARGS:.*II/ \"@contains other_value\" \"msg:'whee %{MATCHED_VARS_NAMES}% test'\"" + ] } ] diff --git a/test/test-cases/regression/variable-MATCHED_VARS_NAMES.json b/test/test-cases/regression/variable-MATCHED_VARS_NAMES.json index a734e71b..6feecbc1 100644 --- a/test/test-cases/regression/variable-MATCHED_VARS_NAMES.json +++ b/test/test-cases/regression/variable-MATCHED_VARS_NAMES.json @@ -2,7 +2,7 @@ { "enabled":1, "version_min":300000, - "title":"Testing Variables :: MATCHED_VARS_NAMES (1/2)", + "title":"Testing Variables :: MATCHED_VARS_NAMES (1/5)", "client":{ "ip":"200.249.12.31", "port":123 @@ -43,7 +43,7 @@ { "enabled":1, "version_min":300000, - "title":"Testing Variables :: MATCHED_VARS_NAMES (2/2)", + "title":"Testing Variables :: MATCHED_VARS_NAMES (2/5)", "client":{ "ip":"200.249.12.31", "port":123 @@ -81,6 +81,133 @@ "SecRule MATCHED_VARS_NAMES \"@contains asdf\" \"\"", "SecRule MATCHED_VARS_NAMES \"@contains value\" \"id:29\"" ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: MATCHED_VARS_NAMES (3/5)", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*" + }, + "uri":"/?keyI=value&keyII=other_value", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "debug_log":"Target value: \"ARGS:keyI\" \\(Variable: MATCHED_VARS_NAMES:ARGS:keyI\\)" + }, + "rules":[ + "SecRuleEngine On", + "SecRule ARGS:keyI \"@contains value\" \"chain,id:28,pass\"", + "SecRule ARGS:keyII \"@contains other_value\" \"chain\"", + "SecRule MATCHED_VARS_NAMES \"@contains asdf\" \"\"", + "SecRule MATCHED_VARS_NAMES:ARGS:keyI \"@contains value\" \"id:29\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: MATCHED_VARS_NAMES (4/5)", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*" + }, + "uri":"/?keyI=value&keyII=other_value", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "debug_log":"Target value: \"ARGS:keyI\" \\(Variable: MATCHED_VARS_NAMES:ARGS:keyI\\)", + "http_code": 302 + }, + "rules":[ + "SecRuleEngine On", + "SecRule ARGS:keyI \"@contains value\" \"chain,id:28,deny,status:302\"", + "SecRule ARGS:keyII \"@contains other_value\" \"chain\"", + "SecRule MATCHED_VARS_NAMES:/^ARGS:.*eyI$/ \"@contains ARGS:keyI\" \"\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: MATCHED_VARS_NAMES (5/5)", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*" + }, + "uri":"/?keyI=value&keyII=other_value", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "debug_log":"Target value: \"ARGS:keyI\" \\(Variable: MATCHED_VARS_NAMES:ARGS:keyI\\)", + "http_code": 302, + "error_log": "whee MATCHED_VARS_NAMES:ARGS:keyI test" + }, + "rules":[ + "SecRuleEngine On", + "SecRule ARGS:keyI \"@contains value\" \"chain,id:28,deny,status:302\"", + "SecRule ARGS:keyII \"@contains other_value\" \"chain\"", + "SecRule MATCHED_VARS_NAMES:/^ARGS:.*eyI$/ \"@contains ARGS:keyI\" \"msg:'whee %{MATCHED_VARS_NAMES}% test'\"" + ] } ] diff --git a/test/test-cases/regression/variable-MATCHED_VAR_NAME.json b/test/test-cases/regression/variable-MATCHED_VAR_NAME.json index 318a3206..cc964a6e 100644 --- a/test/test-cases/regression/variable-MATCHED_VAR_NAME.json +++ b/test/test-cases/regression/variable-MATCHED_VAR_NAME.json @@ -35,9 +35,9 @@ }, "rules":[ "SecRuleEngine On", - "SecRule ARGS:keyI \"@contains value\" \"chain,id:28,pass\"", - "SecRule ARGS:keyII \"@contains other_value\" \"chain\"", - "SecRule MATCHED_VAR_NAME \"@contains asdf\" \"\"" + "SecRule ARGS:keyI \"@contains value\" \"id:28,pass\"", + "SecRule ARGS:keyII \"@contains other_value\" \"id:29,pass\"", + "SecRule MATCHED_VAR_NAME \"@contains asdf\" \"id:30,pass\"" ] }, {