diff --git a/headers/modsecurity/transaction.h b/headers/modsecurity/transaction.h index 194e6805..ae3ae619 100644 --- a/headers/modsecurity/transaction.h +++ b/headers/modsecurity/transaction.h @@ -273,6 +273,11 @@ class Transaction { */ std::list< std::pair > m_ruleRemoteTargetByTag; + /** + * + */ + std::list< std::pair > m_ruleRemoteTargetById; + /** * The list m_auditLogModifier contains modifications to the `auditlogs' * for this specific request, those modifications can happens via the diff --git a/src/Makefile.am b/src/Makefile.am index 3b08cbc7..10546ba1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -104,6 +104,7 @@ ACTIONS = \ actions/ctl_request_body_processor_json.cc \ actions/ctl_request_body_processor_xml.cc \ actions/ctl_rule_remove_target_by_tag.cc \ + actions/ctl_rule_remove_target_by_id.cc \ actions/init_col.cc \ actions/deny.cc \ actions/log.cc \ diff --git a/src/actions/ctl_rule_remove_target_by_id.cc b/src/actions/ctl_rule_remove_target_by_id.cc new file mode 100644 index 00000000..913fa95b --- /dev/null +++ b/src/actions/ctl_rule_remove_target_by_id.cc @@ -0,0 +1,55 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 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 "actions/ctl_rule_remove_target_by_id.h" + +#include +#include + +#include "modsecurity/transaction.h" + +namespace modsecurity { +namespace actions { + +bool CtlRuleRemoveTargetById::init(std::string *error) { + std::string what(m_parser_payload, 21, m_parser_payload.size() - 21); + std::vector param = split(what, ';'); + + if (param.size() < 2) { + error->assign(what + " is not a valid `ID;VARIABLE'"); + return false; + } + + try { + m_id = std::stoi(param[0]); + } catch(...) { + error->assign("Not able to convert '" + param[0] + + "' into a number"); + return false; + } + + m_target = param[1]; + + return true; +} + +bool CtlRuleRemoveTargetById::evaluate(Rule *rule, Transaction *transaction) { + transaction->m_ruleRemoteTargetById.push_back( + std::make_pair(m_id, m_target)); + return true; +} + +} // namespace actions +} // namespace modsecurity diff --git a/src/actions/ctl_rule_remove_target_by_id.h b/src/actions/ctl_rule_remove_target_by_id.h new file mode 100644 index 00000000..b9d714dd --- /dev/null +++ b/src/actions/ctl_rule_remove_target_by_id.h @@ -0,0 +1,44 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 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 "actions/action.h" +#include "modsecurity/transaction.h" +#include "utils.h" + +#ifndef SRC_ACTIONS_CTL_RULE_REMOVE_TARGET_BY_ID_H_ +#define SRC_ACTIONS_CTL_RULE_REMOVE_TARGET_BY_ID_H_ + +namespace modsecurity { +namespace actions { + + +class CtlRuleRemoveTargetById : public Action { + public: + explicit CtlRuleRemoveTargetById(std::string action) + : Action(action, RunTimeOnlyIfMatchKind) { } + + bool init(std::string *error) override; + bool evaluate(Rule *rule, Transaction *transaction) override; + + int m_id; + std::string m_target; +}; + +} // namespace actions +} // namespace modsecurity + +#endif // SRC_ACTIONS_CTL_RULE_REMOVE_TARGET_BY_ID_H_ diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index d241477f..5a5570ee 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -27,6 +27,7 @@ class Driver; #include "actions/ctl_request_body_processor_json.h" #include "actions/ctl_request_body_processor_xml.h" #include "actions/ctl_rule_remove_target_by_tag.h" +#include "actions/ctl_rule_remove_target_by_id.h" #include "actions/init_col.h" #include "actions/set_sid.h" #include "actions/set_uid.h" @@ -300,6 +301,7 @@ using modsecurity::Variables::XML; %token ACTION_CTL_FORCE_REQ_BODY_VAR %token CONFIG_SEC_COLLECTION_TIMEOUT %token ACTION_CTL_RULE_REMOVE_TARGET_BY_TAG +%token ACTION_CTL_RULE_REMOVE_TARGET_BY_ID %type *> actions %type *> variables @@ -1221,6 +1223,15 @@ act: YYERROR; } } + | ACTION_CTL_RULE_REMOVE_TARGET_BY_ID + { + std::string error; + $$ = new modsecurity::actions::CtlRuleRemoveTargetById($1); + if ($$->init(&error) == false) { + driver.error(@0, error); + YYERROR; + } + } | ACTION_CTL_AUDIT_LOG_PARTS { std::string error; diff --git a/src/parser/seclang-scanner.ll b/src/parser/seclang-scanner.ll index 2f2565c6..33cf85da 100755 --- a/src/parser/seclang-scanner.ll +++ b/src/parser/seclang-scanner.ll @@ -78,6 +78,7 @@ CONFIG_DIR_REQ_BODY_LIMIT_ACTION (?i:SecRequestBodyLimitAction) CONFIG_DIR_RES_BODY_LIMIT_ACTION (?i:SecResponseBodyLimitAction) ACTION_CTL_RULE_REMOVE_TARGET_BY_TAG (?i:ctl:ruleRemoveTargetByTag) +ACTION_CTL_RULE_REMOVE_TARGET_BY_ID (?i:ctl:ruleRemoveTargetById) CONFIG_DIR_GEO_DB (?i:SecGeoLookupDb) @@ -237,6 +238,7 @@ CONFIG_DIR_UNICODE_MAP_FILE (?i:SecUnicodeMapFile) %{ /* Remove Rules */ %} {CONFIG_SEC_REMOVE_RULES_BY_ID}[ ]{FREE_TEXT_NEW_LINE} { return yy::seclang_parser::make_CONFIG_SEC_RULE_REMOVE_BY_ID(strchr(yytext, ' ') + 1, *driver.loc.back()); } {ACTION_CTL_RULE_REMOVE_TARGET_BY_TAG}[=]{CONFIG_VALUE_PATH2} { return yy::seclang_parser::make_ACTION_CTL_RULE_REMOVE_TARGET_BY_TAG(yytext, *driver.loc.back()); } +{ACTION_CTL_RULE_REMOVE_TARGET_BY_ID}[=]{CONFIG_VALUE_PATH2} { return yy::seclang_parser::make_ACTION_CTL_RULE_REMOVE_TARGET_BY_ID(yytext, *driver.loc.back()); } %{ /* Upload */ %} {CONFIG_UPLOAD_FILE_LIMIT}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_UPLOAD_FILE_LIMIT(strchr(yytext, ' ') + 1, *driver.loc.back()); } diff --git a/src/rule.cc b/src/rule.cc index 195c214f..c97f115f 100644 --- a/src/rule.cc +++ b/src/rule.cc @@ -357,6 +357,22 @@ bool Rule::evaluate(Transaction *trasn) { if (ignoreVariable) { continue; } + for (auto &i : trasn->m_ruleRemoteTargetById) { + int id = i.first; + std::string args = i.second; + if (rule_id != id) { + continue; + } + if (args == v->m_key) { + trasn->debug(9, "Variable: " + v->m_key + + " was excluded by ruleRemoteTargetById..."); + ignoreVariable = true; + break; + } + } + if (ignoreVariable) { + continue; + } std::string value = v->m_value; int none = 0; 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 new file mode 100644 index 00000000..a7050191 --- /dev/null +++ b/test/test-cases/regression/action-ctl_rule_remove_target_by_id.json @@ -0,0 +1,66 @@ +[ + { + "enabled":1, + "version_min":300000, + "title":"Testing CtlRuleRemoteTargetById (1)", + "expected":{ + "debug_log": "Variable: ARGS:pwd was excluded by ruleRemoteTargetById..." + }, + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120", + "Content-Type": "text/xml" + }, + "uri":"/wp-login.php?whee&pwd=lhebs", + "method":"GET", + "body": [ ] + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "rules":[ + "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'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing CtlRuleRemoteTargetById (2)", + "expected":{ + "debug_log": "Target value: .*Variable: ARGS:pwd" + }, + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120", + "Content-Type": "text/xml" + }, + "uri":"/wp-login.php?whee&pwd=lhebs", + "method":"GET", + "body": [ ] + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "rules":[ + "SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:9002100,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=123;ARGS:pwd\"", + "SecRule ARGS \"@contais whe\" \"id:1,phase:3,t:none,nolog,pass,tag:'CRS2'\"" + ] + } +]