diff --git a/headers/modsecurity/transaction.h b/headers/modsecurity/transaction.h index 87267dc6..c8b3b1b5 100644 --- a/headers/modsecurity/transaction.h +++ b/headers/modsecurity/transaction.h @@ -283,6 +283,11 @@ class Transaction { */ std::list< std::pair > m_ruleRemoveTargetById; + /** + * + */ + int m_requestBodyAccess; + /** * 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 870b8dee..d7d3d7cb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -106,6 +106,7 @@ ACTIONS = \ actions/ctl_rule_remove_target_by_tag.cc \ actions/ctl_rule_remove_target_by_id.cc \ actions/ctl_rule_remove_by_id.cc \ + actions/ctl_request_body_access.cc\ actions/init_col.cc \ actions/deny.cc \ actions/log.cc \ diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index 57c846e3..c61ce7a1 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -29,6 +29,7 @@ class Driver; #include "actions/ctl_rule_remove_target_by_tag.h" #include "actions/ctl_rule_remove_target_by_id.h" #include "actions/ctl_rule_remove_by_id.h" +#include "actions/ctl_request_body_access.h" #include "actions/init_col.h" #include "actions/set_sid.h" #include "actions/set_uid.h" @@ -304,6 +305,7 @@ using modsecurity::Variables::XML; %token ACTION_CTL_RULE_REMOVE_TARGET_BY_TAG %token ACTION_CTL_RULE_REMOVE_TARGET_BY_ID %token ACTION_CTL_RULE_REMOVE_BY_ID +%token ACTION_CTL_REQUEST_BODY_ACCESS %type *> actions %type *> variables @@ -1252,6 +1254,24 @@ act: YYERROR; } } + | ACTION_CTL_REQUEST_BODY_ACCESS CONFIG_VALUE_ON + { + std::string error; + $$ = new modsecurity::actions::CtlRequestBodyAccess($1 + "true"); + if ($$->init(&error) == false) { + driver.error(@0, error); + YYERROR; + } + } + | ACTION_CTL_REQUEST_BODY_ACCESS CONFIG_VALUE_OFF + { + std::string error; + $$ = new modsecurity::actions::CtlRequestBodyAccess($1 + "false"); + if ($$->init(&error) == false) { + driver.error(@0, error); + YYERROR; + } + } | ACTION_CTL_FORCE_REQ_BODY_VAR CONFIG_VALUE_ON { $$ = Action::instantiate($1); diff --git a/src/parser/seclang-scanner.ll b/src/parser/seclang-scanner.ll index 5ca24a79..d68c0888 100755 --- a/src/parser/seclang-scanner.ll +++ b/src/parser/seclang-scanner.ll @@ -80,6 +80,7 @@ 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) ACTION_CTL_RULE_REMOVE_BY_ID (?i:ctl:ruleRemoveById) +ACTION_CTL_REQUEST_BODY_ACCESS (?i:ctl:requestBodyAccess) CONFIG_DIR_GEO_DB (?i:SecGeoLookupDb) @@ -235,6 +236,7 @@ CONFIG_DIR_UNICODE_MAP_FILE (?i:SecUnicodeMapFile) {ACTION_CTL_RULE_ENGINE}= { return yy::seclang_parser::make_ACTION_CTL_RULE_ENGINE(yytext, *driver.loc.back()); } {ACTION_CTL_AUDIT_ENGINE}= { return yy::seclang_parser::make_ACTION_CTL_AUDIT_ENGINE(yytext, *driver.loc.back()); } {ACTION_CTL_FORCE_REQ_BODY_VAR}= { return yy::seclang_parser::make_ACTION_CTL_FORCE_REQ_BODY_VAR(yytext, *driver.loc.back()); } +{ACTION_CTL_REQUEST_BODY_ACCESS}= { return yy::seclang_parser::make_ACTION_CTL_REQUEST_BODY_ACCESS(yytext, *driver.loc.back()); } %{ /* Remove Rules */ %} diff --git a/src/transaction.cc b/src/transaction.cc index c71bb15f..73874568 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -43,8 +43,10 @@ #include "src/unique_id.h" #include "src/utils.h" #include "modsecurity/rule.h" +#include "modsecurity/rules_properties.h" #include "src/actions/allow.h" + using modsecurity::actions::Action; using modsecurity::RequestBodyProcessor::Multipart; using modsecurity::RequestBodyProcessor::XML; @@ -113,6 +115,7 @@ Transaction::Transaction(ModSecurity *ms, Rules *rules, void *logCbData) m_requestHeadersNames(NULL), m_responseHeadersNames(NULL), m_responseContentType(NULL), + m_requestBodyAccess(Rules::PropertyNotSetConfigBoolean), m_marker(""), m_allowType(modsecurity::actions::NoneAllowType), m_skip_next(0), @@ -618,7 +621,7 @@ int Transaction::processRequestBody() { debug(4, "Starting phase REQUEST_BODY. (SecRules 2)"); #endif - if (m_rules->m_secRuleEngine == Rules::DisabledRuleEngine) { + if (m_rules->m_secRuleEngine == RulesProperties::DisabledRuleEngine) { #ifndef NO_LOGS debug(4, "Rule engine disabled, returning..."); #endif @@ -719,6 +722,29 @@ int Transaction::processRequestBody() { m_collections.storeOrUpdateFirst("REQBODY_PROCESSOR_ERROR", "0"); } +#if 1 + if (m_rules->m_secRequestBodyAccess != RulesProperties::TrueConfigBoolean) { + if (m_requestBodyAccess != RulesProperties::TrueConfigBoolean) { + debug(4, "Request body processing is disabled"); + + this->m_rules->evaluate(modsecurity::RequestBodyPhase, this); + return true; + } else { + debug(4, "Request body processing is disabled, but " \ + "enabled to this transaction due to ctl:requestBodyAccess " \ + "action"); + } + } else { + if (m_requestBodyAccess == RulesProperties::FalseConfigBoolean) { + debug(4, "Request body processing is enabled, but " \ + "disable to this transaction due to ctl:requestBodyAccess " \ + "action"); + this->m_rules->evaluate(modsecurity::RequestBodyPhase, this); + return true; + } + } +#endif + /** * FIXME: This variable should be calculated on demand, it is * computationally intensive. diff --git a/test/test-cases/regression/variable-FULL_REQUEST.json b/test/test-cases/regression/variable-FULL_REQUEST.json index 2da4f6e9..caf612db 100644 --- a/test/test-cases/regression/variable-FULL_REQUEST.json +++ b/test/test-cases/regression/variable-FULL_REQUEST.json @@ -55,6 +55,7 @@ }, "rules":[ "SecRuleEngine On", + "SecRequestBodyAccess On", "SecRule FULL_REQUEST \"@contains small_text_file.txt\" \"id:1,phase:3,pass,t:trim\"" ] } diff --git a/test/test-cases/regression/variable-FULL_REQUEST_LENGTH.json b/test/test-cases/regression/variable-FULL_REQUEST_LENGTH.json index e7d3b1ab..9bba74d4 100644 --- a/test/test-cases/regression/variable-FULL_REQUEST_LENGTH.json +++ b/test/test-cases/regression/variable-FULL_REQUEST_LENGTH.json @@ -55,6 +55,7 @@ }, "rules":[ "SecRuleEngine On", + "SecRequestBodyAccess On", "SecRule FULL_REQUEST_LENGTH \"@contains small_text_file.txt\" \"id:1,phase:3,pass,t:trim\"" ] } diff --git a/test/test-cases/regression/variable-REQUEST_BODY.json b/test/test-cases/regression/variable-REQUEST_BODY.json index b1f99b45..34206c35 100644 --- a/test/test-cases/regression/variable-REQUEST_BODY.json +++ b/test/test-cases/regression/variable-REQUEST_BODY.json @@ -55,6 +55,7 @@ }, "rules":[ "SecRuleEngine On", + "SecRequestBodyAccess On", "SecRule REQUEST_BODY \"@contains small_text_file.txt\" \"id:1,phase:3,pass,t:trim\"" ] } diff --git a/test/test-cases/regression/variable-REQUEST_BODY_LENGTH.json b/test/test-cases/regression/variable-REQUEST_BODY_LENGTH.json index d7a8e910..2515eb55 100644 --- a/test/test-cases/regression/variable-REQUEST_BODY_LENGTH.json +++ b/test/test-cases/regression/variable-REQUEST_BODY_LENGTH.json @@ -55,6 +55,7 @@ }, "rules":[ "SecRuleEngine On", + "SecRequestBodyAccess On", "SecRule REQUEST_BODY_LENGTH \"@contains small_text_file.txt\" \"id:1,phase:3,pass,t:trim\"" ] }