mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 13:56:01 +03:00
Adds support to SecRuleUpdateTargetById
This commit is contained in:
parent
9ce7d022c2
commit
e14dc602e5
@ -277,4 +277,5 @@ TESTS+=test/test-cases/secrules-language-tests/operators/detectXSS.json
|
|||||||
TESTS+=test/test-cases/secrules-language-tests/operators/eq.json
|
TESTS+=test/test-cases/secrules-language-tests/operators/eq.json
|
||||||
TESTS+=test/test-cases/regression/offset-variable.json
|
TESTS+=test/test-cases/regression/offset-variable.json
|
||||||
TESTS+=test/test-cases/regression/config-update-target-by-tag.json
|
TESTS+=test/test-cases/regression/config-update-target-by-tag.json
|
||||||
|
TESTS+=test/test-cases/regression/config-update-target-by-id.json
|
||||||
|
|
||||||
|
@ -54,7 +54,12 @@ class RulesExceptions {
|
|||||||
std::unique_ptr<std::vector<std::unique_ptr<Variables::Variable> > > var,
|
std::unique_ptr<std::vector<std::unique_ptr<Variables::Variable> > > var,
|
||||||
std::string *error);
|
std::string *error);
|
||||||
|
|
||||||
|
bool loadUpdateTargetById(double id,
|
||||||
|
std::unique_ptr<std::vector<std::unique_ptr<Variables::Variable> > > var,
|
||||||
|
std::string *error);
|
||||||
|
|
||||||
std::unordered_multimap<std::string, std::unique_ptr<Variables::Variable>> m_variable_update_target_by_tag;
|
std::unordered_multimap<std::string, std::unique_ptr<Variables::Variable>> m_variable_update_target_by_tag;
|
||||||
|
std::unordered_multimap<double, std::unique_ptr<Variables::Variable>> m_variable_update_target_by_id;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::list<std::pair<int, int> > m_ranges;
|
std::list<std::pair<int, int> > m_ranges;
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -559,6 +559,7 @@ using modsecurity::operators::Operator;
|
|||||||
CONFIG_SEC_REMOTE_RULES_FAIL_ACTION "CONFIG_SEC_REMOTE_RULES_FAIL_ACTION"
|
CONFIG_SEC_REMOTE_RULES_FAIL_ACTION "CONFIG_SEC_REMOTE_RULES_FAIL_ACTION"
|
||||||
CONFIG_SEC_RULE_REMOVE_BY_ID "CONFIG_SEC_RULE_REMOVE_BY_ID"
|
CONFIG_SEC_RULE_REMOVE_BY_ID "CONFIG_SEC_RULE_REMOVE_BY_ID"
|
||||||
CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG "CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG"
|
CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG "CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG"
|
||||||
|
CONFIG_SEC_RULE_UPDATE_TARGET_BY_ID "CONFIG_SEC_RULE_UPDATE_TARGET_BY_ID"
|
||||||
CONFIG_UPDLOAD_KEEP_FILES "CONFIG_UPDLOAD_KEEP_FILES"
|
CONFIG_UPDLOAD_KEEP_FILES "CONFIG_UPDLOAD_KEEP_FILES"
|
||||||
CONFIG_UPDLOAD_SAVE_TMP_FILES "CONFIG_UPDLOAD_SAVE_TMP_FILES"
|
CONFIG_UPDLOAD_SAVE_TMP_FILES "CONFIG_UPDLOAD_SAVE_TMP_FILES"
|
||||||
CONFIG_UPLOAD_DIR "CONFIG_UPLOAD_DIR"
|
CONFIG_UPLOAD_DIR "CONFIG_UPLOAD_DIR"
|
||||||
@ -1186,6 +1187,32 @@ expression:
|
|||||||
YYERROR;
|
YYERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
| CONFIG_SEC_RULE_UPDATE_TARGET_BY_ID variables
|
||||||
|
{
|
||||||
|
std::string error;
|
||||||
|
double ruleId;
|
||||||
|
try {
|
||||||
|
ruleId = std::stod($1);
|
||||||
|
} catch (...) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "SecRuleUpdateTargetById: failed to load:";
|
||||||
|
ss << "The input \"" + $1 + "\" does not ";
|
||||||
|
ss << "seems to be a valid rule id.";
|
||||||
|
ss << ". ";
|
||||||
|
driver.error(@0, ss.str());
|
||||||
|
YYERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (driver.m_exceptions.loadUpdateTargetById(ruleId, std::move($2), &error) == false) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "SecRuleUpdateTargetById: failed to load:";
|
||||||
|
ss << $1;
|
||||||
|
ss << ". ";
|
||||||
|
ss << error;
|
||||||
|
driver.error(@0, ss.str());
|
||||||
|
YYERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Debug log: start */
|
/* Debug log: start */
|
||||||
| CONFIG_DIR_DEBUG_LVL
|
| CONFIG_DIR_DEBUG_LVL
|
||||||
{
|
{
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -289,6 +289,7 @@ CONFIG_SEC_REMOTE_RULES (?i:SecRemoteRules)
|
|||||||
CONFIG_SEC_REMOTE_RULES_FAIL_ACTION (?i:SecRemoteRulesFailAction)
|
CONFIG_SEC_REMOTE_RULES_FAIL_ACTION (?i:SecRemoteRulesFailAction)
|
||||||
CONFIG_SEC_REMOVE_RULES_BY_ID (?i:SecRuleRemoveById)
|
CONFIG_SEC_REMOVE_RULES_BY_ID (?i:SecRuleRemoveById)
|
||||||
CONFIG_SEC_UPDATE_TARGET_BY_TAG (?i:SecRuleUpdateTargetByTag)
|
CONFIG_SEC_UPDATE_TARGET_BY_TAG (?i:SecRuleUpdateTargetByTag)
|
||||||
|
CONFIG_SEC_UPDATE_TARGET_BY_ID (?i:SecRuleUpdateTargetById)
|
||||||
CONFIG_UPDLOAD_KEEP_FILES (?i:SecUploadKeepFiles)
|
CONFIG_UPDLOAD_KEEP_FILES (?i:SecUploadKeepFiles)
|
||||||
CONFIG_UPDLOAD_SAVE_TMP_FILES (?i:SecTmpSaveUploadedFiles)
|
CONFIG_UPDLOAD_SAVE_TMP_FILES (?i:SecTmpSaveUploadedFiles)
|
||||||
CONFIG_UPLOAD_DIR (?i:SecUploadDir)
|
CONFIG_UPLOAD_DIR (?i:SecUploadDir)
|
||||||
@ -590,7 +591,9 @@ EQUALS_MINUS (?i:=\-)
|
|||||||
{CONFIG_DIR_UNICODE_MAP_FILE}[ ]{FREE_TEXT_NEW_LINE} { return p::make_CONFIG_DIR_UNICODE_MAP_FILE(strchr(yytext, ' ') + 1, *driver.loc.back()); }
|
{CONFIG_DIR_UNICODE_MAP_FILE}[ ]{FREE_TEXT_NEW_LINE} { return p::make_CONFIG_DIR_UNICODE_MAP_FILE(strchr(yytext, ' ') + 1, *driver.loc.back()); }
|
||||||
{CONFIG_SEC_REMOVE_RULES_BY_ID}[ ]+{FREE_TEXT_NEW_LINE} { return p::make_CONFIG_SEC_RULE_REMOVE_BY_ID(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }
|
{CONFIG_SEC_REMOVE_RULES_BY_ID}[ ]+{FREE_TEXT_NEW_LINE} { return p::make_CONFIG_SEC_RULE_REMOVE_BY_ID(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }
|
||||||
{CONFIG_SEC_UPDATE_TARGET_BY_TAG}[ ]+["]{FREE_TEXT_NEW_LINE}["] { state_variable_from = 1; BEGIN(TRANSACTION_TO_VARIABLE); return p::make_CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }
|
{CONFIG_SEC_UPDATE_TARGET_BY_TAG}[ ]+["]{FREE_TEXT_NEW_LINE}["] { state_variable_from = 1; BEGIN(TRANSACTION_TO_VARIABLE); return p::make_CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }
|
||||||
{CONFIG_SEC_UPDATE_TARGET_BY_TAG}[ ]+{FREE_TEXT_SPACE_COMMA_QUOTE} { state_variable_from = 1; BEGIN(TRANSACTION_TO_VARIABLE); return p::make_CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }
|
{CONFIG_SEC_UPDATE_TARGET_BY_TAG}[ ]+{FREE_TEXT_SPACE_COMMA_QUOTE} { state_variable_from = 1; BEGIN(TRANSACTION_TO_VARIABLE); return p::make_CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }
|
||||||
|
{CONFIG_SEC_UPDATE_TARGET_BY_ID}[ ]+["]{FREE_TEXT_NEW_LINE}["] { state_variable_from = 1; BEGIN(TRANSACTION_TO_VARIABLE); return p::make_CONFIG_SEC_RULE_UPDATE_TARGET_BY_ID(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }
|
||||||
|
{CONFIG_SEC_UPDATE_TARGET_BY_ID}[ ]+{FREE_TEXT_SPACE_COMMA_QUOTE} { state_variable_from = 1; BEGIN(TRANSACTION_TO_VARIABLE); return p::make_CONFIG_SEC_RULE_UPDATE_TARGET_BY_ID(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }
|
||||||
{CONFIG_UPDLOAD_KEEP_FILES} { return p::make_CONFIG_UPDLOAD_KEEP_FILES(yytext, *driver.loc.back()); }
|
{CONFIG_UPDLOAD_KEEP_FILES} { return p::make_CONFIG_UPDLOAD_KEEP_FILES(yytext, *driver.loc.back()); }
|
||||||
{CONFIG_UPDLOAD_SAVE_TMP_FILES} { return p::make_CONFIG_UPDLOAD_SAVE_TMP_FILES(yytext, *driver.loc.back()); }
|
{CONFIG_UPDLOAD_SAVE_TMP_FILES} { return p::make_CONFIG_UPDLOAD_SAVE_TMP_FILES(yytext, *driver.loc.back()); }
|
||||||
{CONFIG_UPLOAD_DIR}[ ]{CONFIG_VALUE_PATH} { return p::make_CONFIG_UPLOAD_DIR(strchr(yytext, ' ') + 1, *driver.loc.back()); }
|
{CONFIG_UPLOAD_DIR}[ ]{CONFIG_VALUE_PATH} { return p::make_CONFIG_UPLOAD_DIR(strchr(yytext, ' ') + 1, *driver.loc.back()); }
|
||||||
|
35
src/rule.cc
35
src/rule.cc
@ -418,6 +418,7 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
|
|||||||
Transaction *trans) {
|
Transaction *trans) {
|
||||||
std::list<const std::string*> exclusions;
|
std::list<const std::string*> exclusions;
|
||||||
std::list<const std::string*> exclusions_update_by_tag_remove;
|
std::list<const std::string*> exclusions_update_by_tag_remove;
|
||||||
|
std::list<const std::string*> exclusions_update_by_id_remove;
|
||||||
std::vector<Variables::Variable *> variables;
|
std::vector<Variables::Variable *> variables;
|
||||||
std::vector<std::unique_ptr<collection::Variable>> finalVars;
|
std::vector<std::unique_ptr<collection::Variable>> finalVars;
|
||||||
|
|
||||||
@ -441,6 +442,23 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto &a : trans->m_rules->m_exceptions.m_variable_update_target_by_id) {
|
||||||
|
if (m_ruleId != a.first) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (a.second->m_isExclusion) {
|
||||||
|
std::vector<const collection::Variable *> z;
|
||||||
|
a.second->evaluateInternal(trans, this, &z);
|
||||||
|
for (auto &y : z) {
|
||||||
|
exclusions_update_by_id_remove.push_back(y->m_key);
|
||||||
|
}
|
||||||
|
exclusions_update_by_id_remove.push_back(&a.second->m_name);
|
||||||
|
} else {
|
||||||
|
Variable *b = a.second.get();
|
||||||
|
variables.push_back(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < variables.size(); i++) {
|
for (int i = 0; i < variables.size(); i++) {
|
||||||
Variable *variable = variables.at(i);
|
Variable *variable = variables.at(i);
|
||||||
if (variable->m_isExclusion) {
|
if (variable->m_isExclusion) {
|
||||||
@ -452,6 +470,7 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
|
|||||||
exclusions.push_back(&variable->m_name);
|
exclusions.push_back(&variable->m_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < variables.size(); i++) {
|
for (int i = 0; i < variables.size(); i++) {
|
||||||
Variable *variable = variables.at(i);
|
Variable *variable = variables.at(i);
|
||||||
std::vector<const collection::Variable *> e;
|
std::vector<const collection::Variable *> e;
|
||||||
@ -491,6 +510,22 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (std::find_if(exclusions_update_by_id_remove.begin(),
|
||||||
|
exclusions_update_by_id_remove.end(),
|
||||||
|
[key](const 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
|
||||||
|
if (v->m_dynamic) {
|
||||||
|
delete v;
|
||||||
|
v = NULL;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto &i : trans->m_ruleRemoveTargetByTag) {
|
for (auto &i : trans->m_ruleRemoveTargetByTag) {
|
||||||
std::string tag = i.first;
|
std::string tag = i.first;
|
||||||
std::string args = i.second;
|
std::string args = i.second;
|
||||||
|
@ -42,6 +42,17 @@ bool RulesExceptions::loadUpdateTargetByTag(const std::string &tag,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RulesExceptions::loadUpdateTargetById(double id,
|
||||||
|
std::unique_ptr<std::vector<std::unique_ptr<Variables::Variable> > > var,
|
||||||
|
std::string *error) {
|
||||||
|
|
||||||
|
for (auto &i : *var) {
|
||||||
|
m_variable_update_target_by_id.emplace(std::pair<double, std::unique_ptr<Variables::Variable>>(id , std::move(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool RulesExceptions::load(const std::string &a, std::string *error) {
|
bool RulesExceptions::load(const std::string &a, std::string *error) {
|
||||||
bool added = false;
|
bool added = false;
|
||||||
std::vector<std::string> toRemove = utils::string::ssplit(a, ' ');
|
std::vector<std::string> toRemove = utils::string::ssplit(a, ' ');
|
||||||
@ -146,6 +157,9 @@ bool RulesExceptions::merge(RulesExceptions& from) {
|
|||||||
m_variable_update_target_by_tag.emplace(std::pair<std::string, std::unique_ptr<Variables::Variable>>(p.first, std::move(p.second)));
|
m_variable_update_target_by_tag.emplace(std::pair<std::string, std::unique_ptr<Variables::Variable>>(p.first, std::move(p.second)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto &p : from.m_variable_update_target_by_id) {
|
||||||
|
m_variable_update_target_by_id.emplace(std::pair<double, std::unique_ptr<Variables::Variable>>(p.first, std::move(p.second)));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
41
test/test-cases/regression/config-update-target-by-id.json
Normal file
41
test/test-cases/regression/config-update-target-by-id.json
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"title":"SecRuleUpdateTargetById",
|
||||||
|
"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":"/?key=value&key=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":"ARGS:key is part of the exclusion list \\(from update by ID\\), skipping"
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleUpdateTargetById 1 !ARGS",
|
||||||
|
"SecRule ARGS \"@contains test\" \"id:1,pass,t:trim,tag:'test'\""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
Loading…
x
Reference in New Issue
Block a user