Adds support for update target by message

This commit is contained in:
Felipe Zimmerle 2017-11-06 23:27:31 -03:00
parent 7d7c0c03c5
commit 4d7fd5c30a
No known key found for this signature in database
GPG Key ID: E6DFB08CE8B11277
11 changed files with 5108 additions and 4933 deletions

View File

@ -2,6 +2,8 @@
v3.0.????? - ?
---------------------------
- Adds support for update target by message.
[Issue #1474 - @zimmerle, @victorhora]
- Adds support to SecRuleScript directive.
[Issue #994 - @zimmerle]
- Adds support for the exec action.

View File

@ -289,4 +289,5 @@ TESTS+=test/test-cases/regression/collection-resource.json
TESTS+=test/test-cases/regression/operator-inpectFile.json
TESTS+=test/test-cases/regression/action-exec.json
TESTS+=test/test-cases/regression/directive-sec_rule_script.json
TESTS+=test/test-cases/regression/config-update-target-by-msg.json

View File

@ -52,6 +52,10 @@ class RulesExceptions {
bool loadRemoveRuleByMsg(const std::string &msg, std::string *error);
bool loadUpdateTargetByMsg(const std::string &msg,
std::unique_ptr<std::vector<std::unique_ptr<Variables::Variable> > > var,
std::string *error);
bool loadUpdateTargetByTag(const std::string &tag,
std::unique_ptr<std::vector<std::unique_ptr<Variables::Variable> > > var,
std::string *error);
@ -61,6 +65,7 @@ class RulesExceptions {
std::string *error);
std::unordered_multimap<std::shared_ptr<std::string>, std::unique_ptr<Variables::Variable>> m_variable_update_target_by_tag;
std::unordered_multimap<std::shared_ptr<std::string>, std::unique_ptr<Variables::Variable>> m_variable_update_target_by_msg;
std::unordered_multimap<double, std::unique_ptr<Variables::Variable>> m_variable_update_target_by_id;
std::list<std::string> m_remove_rule_by_msg;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -575,6 +575,7 @@ using modsecurity::operators::Operator;
CONFIG_SEC_RULE_REMOVE_BY_ID "CONFIG_SEC_RULE_REMOVE_BY_ID"
CONFIG_SEC_RULE_REMOVE_BY_MSG "CONFIG_SEC_RULE_REMOVE_BY_MSG"
CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG "CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG"
CONFIG_SEC_RULE_UPDATE_TARGET_BY_MSG "CONFIG_SEC_RULE_UPDATE_TARGET_BY_MSG"
CONFIG_SEC_RULE_UPDATE_TARGET_BY_ID "CONFIG_SEC_RULE_UPDATE_TARGET_BY_ID"
CONFIG_SEC_RULE_UPDATE_ACTION_BY_ID "CONFIG_SEC_RULE_UPDATE_ACTION_BY_ID"
CONFIG_UPDLOAD_KEEP_FILES "CONFIG_UPDLOAD_KEEP_FILES"
@ -1289,6 +1290,19 @@ expression:
YYERROR;
}
}
| CONFIG_SEC_RULE_UPDATE_TARGET_BY_MSG variables
{
std::string error;
if (driver.m_exceptions.loadUpdateTargetByMsg($1, std::move($2), &error) == false) {
std::stringstream ss;
ss << "SecRuleUpdateTargetByMsg: failed to load:";
ss << $1;
ss << ". ";
ss << error;
driver.error(@0, ss.str());
YYERROR;
}
}
| CONFIG_SEC_RULE_UPDATE_TARGET_BY_ID variables
{
std::string error;

File diff suppressed because it is too large Load Diff

View File

@ -297,6 +297,7 @@ CONFIG_SEC_REMOTE_RULES_FAIL_ACTION (?i:SecRemoteRulesFailAction)
CONFIG_SEC_REMOVE_RULES_BY_ID (?i:SecRuleRemoveById)
CONFIG_SEC_REMOVE_RULES_BY_MSG (?i:SecRuleRemoveByMsg)
CONFIG_SEC_UPDATE_TARGET_BY_TAG (?i:SecRuleUpdateTargetByTag)
CONFIG_SEC_UPDATE_TARGET_BY_MSG (?i:SecRuleUpdateTargetByMsg)
CONFIG_SEC_UPDATE_TARGET_BY_ID (?i:SecRuleUpdateTargetById)
CONFIG_SEC_UPDATE_ACTION_BY_ID (?i:SecRuleUpdateActionById)
CONFIG_UPDLOAD_KEEP_FILES (?i:SecUploadKeepFiles)
@ -631,6 +632,8 @@ EQUALS_MINUS (?i:=\-)
{CONFIG_SEC_REMOVE_RULES_BY_MSG}[ \t]+["]{FREE_TEXT_NEW_LINE}["] { return p::make_CONFIG_SEC_RULE_REMOVE_BY_MSG(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_MSG}[ ]+["]{FREE_TEXT_NEW_LINE}["] { state_variable_from = 1; BEGIN(TRANSACTION_TO_VARIABLE); return p::make_CONFIG_SEC_RULE_UPDATE_TARGET_BY_MSG(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }
{CONFIG_SEC_UPDATE_TARGET_BY_MSG}[ ]+{FREE_TEXT_SPACE_COMMA_QUOTE} { state_variable_from = 1; BEGIN(TRANSACTION_TO_VARIABLE); return p::make_CONFIG_SEC_RULE_UPDATE_TARGET_BY_MSG(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_SEC_UPDATE_ACTION_BY_ID}[ ]+["]{FREE_TEXT_NEW_LINE}["] { BEGIN(TRANSACTION_FROM_OPERATOR_TO_ACTIONS); return p::make_CONFIG_SEC_RULE_UPDATE_ACTION_BY_ID(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }

View File

@ -433,6 +433,7 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
Transaction *trans) {
std::list<std::string> exclusions;
std::list<std::string> exclusions_update_by_tag_remove;
std::list<std::string> exclusions_update_by_msg_remove;
std::list<std::string> exclusions_update_by_id_remove;
std::vector<Variables::Variable *> variables;
std::vector<std::unique_ptr<collection::Variable>> finalVars;
@ -458,6 +459,25 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
}
}
for (auto &a : trans->m_rules->m_exceptions.m_variable_update_target_by_msg) {
if (containsMsg(*a.first.get(), trans) == false) {
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_msg_remove.push_back(std::string(y->m_key));
delete y;
}
exclusions_update_by_msg_remove.push_back(std::string(a.second->m_name));
} else {
Variable *b = a.second.get();
variables.push_back(b);
}
}
for (auto &a : trans->m_rules->m_exceptions.m_variable_update_target_by_id) {
if (m_ruleId != a.first) {
continue;
@ -527,6 +547,20 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
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; })

View File

@ -39,6 +39,17 @@ bool RulesExceptions::loadRemoveRuleByMsg(const std::string &msg,
}
bool RulesExceptions::loadUpdateTargetByMsg(const std::string &msg,
std::unique_ptr<std::vector<std::unique_ptr<Variables::Variable> > > var,
std::string *error) {
for (auto &i : *var) {
m_variable_update_target_by_msg.emplace(std::pair<std::shared_ptr<std::string>, std::unique_ptr<Variables::Variable>>(std::make_shared<std::string>(msg), std::move(i)));
}
return true;
}
bool RulesExceptions::loadUpdateTargetByTag(const std::string &tag,
std::unique_ptr<std::vector<std::unique_ptr<Variables::Variable> > > var,
std::string *error) {
@ -167,6 +178,10 @@ bool RulesExceptions::merge(RulesExceptions& from) {
m_variable_update_target_by_tag.emplace(std::pair<std::shared_ptr<std::string>, std::unique_ptr<Variables::Variable>>(p.first, std::move(p.second)));
}
for (auto &p : from.m_variable_update_target_by_msg) {
m_variable_update_target_by_msg.emplace(std::pair<std::shared_ptr<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)));
}

View File

@ -0,0 +1,41 @@
[
{
"enabled":1,
"version_min":300000,
"title":"SecRuleUpdateTargetByTag",
"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 msg\\), skipping"
},
"rules":[
"SecRuleUpdateTargetByMsg test !ARGS",
"SecRule ARGS \"@contains test\" \"id:1,pass,t:trim,msg:'test'\""
]
}
]