Adds initial support to SecRuleUpdateTargetByTag

This commit is contained in:
Felipe Zimmerle 2017-07-03 17:07:02 -03:00
parent 65bd06fb7f
commit fba9c20ea1
8 changed files with 6208 additions and 5990 deletions

View File

@ -25,6 +25,7 @@
#include <unordered_map> #include <unordered_map>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <memory>
#endif #endif
#ifndef HEADERS_MODSECURITY_RULES_EXCEPTIONS_H_ #ifndef HEADERS_MODSECURITY_RULES_EXCEPTIONS_H_
@ -34,15 +35,26 @@
namespace modsecurity { namespace modsecurity {
namespace Variables {
class Variable;
}
class RulesExceptions { class RulesExceptions {
public: public:
RulesExceptions() { } RulesExceptions();
~RulesExceptions();
bool load(const std::string &data, std::string *error); bool load(const std::string &data, std::string *error);
bool addRange(int a, int b); bool addRange(int a, int b);
bool addNumber(int a); bool addNumber(int a);
bool contains(int a); bool contains(int a);
bool merge(const RulesExceptions& from); bool merge(RulesExceptions& from);
bool loadUpdateTargetByTag(const std::string &tag,
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;
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

View File

@ -558,6 +558,7 @@ using modsecurity::operators::Operator;
CONFIG_SEC_COLLECTION_TIMEOUT "CONFIG_SEC_COLLECTION_TIMEOUT" CONFIG_SEC_COLLECTION_TIMEOUT "CONFIG_SEC_COLLECTION_TIMEOUT"
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_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"
@ -1172,6 +1173,19 @@ expression:
YYERROR; YYERROR;
} }
} }
| CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG variables
{
std::string error;
if (driver.m_exceptions.loadUpdateTargetByTag($1, std::move($2), &error) == false) {
std::stringstream ss;
ss << "SecRuleUpdateTargetByTag: 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

View File

@ -14,6 +14,7 @@ using modsecurity::Utils::HttpsClient;
using modsecurity::utils::string::parserSanitizer; using modsecurity::utils::string::parserSanitizer;
typedef yy::seclang_parser p; typedef yy::seclang_parser p;
static int state_variable_from = 0;
// Work around an incompatibility in flex (at least versions // Work around an incompatibility in flex (at least versions
// 2.5.31 through 2.5.33): it generates code that does // 2.5.31 through 2.5.33): it generates code that does
@ -287,6 +288,7 @@ CONFIG_SEC_COLLECTION_TIMEOUT (?i:SecCollectionTimeout)
CONFIG_SEC_REMOTE_RULES (?i:SecRemoteRules) 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_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)
@ -312,7 +314,7 @@ CONGIG_DIR_SEC_COOKIE_FORMAT (?i:SecCookieFormat)
CONGIG_DIR_SEC_DATA_DIR (?i:SecDataDir) CONGIG_DIR_SEC_DATA_DIR (?i:SecDataDir)
CONGIG_DIR_SEC_STATUS_ENGINE (?i:SecStatusEngine) CONGIG_DIR_SEC_STATUS_ENGINE (?i:SecStatusEngine)
CONGIG_DIR_SEC_TMP_DIR (?i:SecTmpDir) CONGIG_DIR_SEC_TMP_DIR (?i:SecTmpDir)
DICT_ELEMENT ([^\"| \t]|([^\\]\\\"))+ DICT_ELEMENT ([^\"|,\n \t]|([^\\]\\\"))+
DICT_ELEMENT_WITH_PIPE [^ \t"]+ DICT_ELEMENT_WITH_PIPE [^ \t"]+
@ -347,7 +349,6 @@ EQUALS_MINUS (?i:=\-)
%x TRANSACTION_TO_VARIABLE %x TRANSACTION_TO_VARIABLE
%x EXPECTING_VARIABLE %x EXPECTING_VARIABLE
%x TRANSACTION_FROM_VARIABLE_TO_OPERATOR
%x EXPECTING_OPERATOR %x EXPECTING_OPERATOR
%x COMMENT %x COMMENT
%x EXPECTING_VAR_PARAMETER %x EXPECTING_VAR_PARAMETER
@ -588,6 +589,8 @@ EQUALS_MINUS (?i:=\-)
{CONFIG_DIR_SEC_MARKER}[ \t]+{NEW_LINE_FREE_TEXT} { return p::make_CONFIG_DIR_SEC_MARKER(strchr(yytext, ' ') + 1, *driver.loc.back()); } {CONFIG_DIR_SEC_MARKER}[ \t]+{NEW_LINE_FREE_TEXT} { return p::make_CONFIG_DIR_SEC_MARKER(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_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_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_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()); }
@ -629,6 +632,7 @@ EQUALS_MINUS (?i:=\-)
<TRANSACTION_TO_VARIABLE>{ <TRANSACTION_TO_VARIABLE>{
[ \t]* { BEGIN(EXPECTING_VARIABLE); } [ \t]* { BEGIN(EXPECTING_VARIABLE); }
[ \t]*\"[ \t]* { BEGIN(EXPECTING_VARIABLE); }
} }
<TRANSACTION_FROM_DIRECTIVE_TO_ACTIONS>{ <TRANSACTION_FROM_DIRECTIVE_TO_ACTIONS>{
@ -640,6 +644,16 @@ EQUALS_MINUS (?i:=\-)
<EXPECTING_VARIABLE>{ <EXPECTING_VARIABLE>{
[|] { return p::make_PIPE(*driver.loc.back()); }
[,] { return p::make_PIPE(*driver.loc.back()); }
[ \t]+ { if (state_variable_from == 0) { BEGIN(EXPECTING_OPERATOR); } else { state_variable_from = 0; BEGIN(INITIAL);} }
[ \t]*\" { if (state_variable_from == 0) { BEGIN(EXPECTING_OPERATOR); } else { state_variable_from = 0; BEGIN(INITIAL);} }
[ \t]*[\\\n]*[ \t]* { if (state_variable_from == 0) { BEGIN(EXPECTING_OPERATOR); } else { state_variable_from = 0; BEGIN(INITIAL);} }
[ \t]*[\\\n]*[ \t]*\" { if (state_variable_from == 0) { BEGIN(EXPECTING_OPERATOR); } else { state_variable_from = 0; BEGIN(INITIAL);} }
[ \t]*[\\\r\n]*[ \t]* { if (state_variable_from == 0) { BEGIN(EXPECTING_OPERATOR); } else { state_variable_from = 0; BEGIN(INITIAL);} }
[ \t]*[\\\r\n]*[ \t]*\" { if (state_variable_from == 0) { BEGIN(EXPECTING_OPERATOR); } else { state_variable_from = 0; BEGIN(INITIAL);} }
{VARIABLE_ARGS_COMBINED_SIZE} { return p::make_VARIABLE_ARGS_COMBINED_SIZE(*driver.loc.back()); } {VARIABLE_ARGS_COMBINED_SIZE} { return p::make_VARIABLE_ARGS_COMBINED_SIZE(*driver.loc.back()); }
{VARIABLE_ARGS_GET_NAMES} { return p::make_VARIABLE_ARGS_GET_NAMES(*driver.loc.back()); } {VARIABLE_ARGS_GET_NAMES} { return p::make_VARIABLE_ARGS_GET_NAMES(*driver.loc.back()); }
{VARIABLE_ARGS_NAMES} { return p::make_VARIABLE_ARGS_NAMES(*driver.loc.back()); } {VARIABLE_ARGS_NAMES} { return p::make_VARIABLE_ARGS_NAMES(*driver.loc.back()); }
@ -779,15 +793,14 @@ EQUALS_MINUS (?i:=\-)
['][\/]{DICT_ELEMENT_WITH_PIPE}[\/]['] { BEGIN(EXPECTING_VARIABLE); yyless(yyleng - 0); return p::make_DICT_ELEMENT_REGEXP(std::string(yytext, 2, yyleng-4), *driver.loc.back()); } ['][\/]{DICT_ELEMENT_WITH_PIPE}[\/]['] { BEGIN(EXPECTING_VARIABLE); yyless(yyleng - 0); return p::make_DICT_ELEMENT_REGEXP(std::string(yytext, 2, yyleng-4), *driver.loc.back()); }
['][\/]{DICT_ELEMENT_WITH_PIPE}[\/]['][|] { BEGIN(EXPECTING_VARIABLE); yyless(yyleng - 1); return p::make_DICT_ELEMENT_REGEXP(std::string(yytext, 2, yyleng-4), *driver.loc.back()); } ['][\/]{DICT_ELEMENT_WITH_PIPE}[\/]['][|] { BEGIN(EXPECTING_VARIABLE); yyless(yyleng - 1); return p::make_DICT_ELEMENT_REGEXP(std::string(yytext, 2, yyleng-4), *driver.loc.back()); }
{DICT_ELEMENT} { BEGIN(EXPECTING_VARIABLE); return p::make_DICT_ELEMENT(yytext, *driver.loc.back()); } {DICT_ELEMENT} { BEGIN(EXPECTING_VARIABLE); return p::make_DICT_ELEMENT(yytext, *driver.loc.back()); }
[\/]{DICT_ELEMENT_WITH_PIPE}[\/][,] { BEGIN(EXPECTING_VARIABLE); yyless(yyleng - 1); return p::make_DICT_ELEMENT_REGEXP(std::string(yytext, 1, yyleng-2), *driver.loc.back()); }
['][\/]{DICT_ELEMENT_WITH_PIPE}[\/]['][,] { BEGIN(EXPECTING_VARIABLE); yyless(yyleng - 1); return p::make_DICT_ELEMENT_REGEXP(std::string(yytext, 2, yyleng-4), *driver.loc.back()); }
. { BEGIN(LEXING_ERROR_ACTION); yyless(0); } . { BEGIN(LEXING_ERROR_ACTION); yyless(0); }
["] { return p::make_QUOTATION_MARK(yytext, *driver.loc.back()); } ["] { return p::make_QUOTATION_MARK(yytext, *driver.loc.back()); }
} }
<EXPECTING_VARIABLE,TRANSACTION_FROM_VARIABLE_TO_OPERATOR>{
[ \t]*\" { BEGIN(EXPECTING_OPERATOR); }
[ \t]*\\\n[ \t]*\" { BEGIN(EXPECTING_OPERATOR); }
[ \t]*\\\r\n[ \t]*\" { BEGIN(EXPECTING_OPERATOR); }
}
<EXPECTING_OPERATOR>{ <EXPECTING_OPERATOR>{
{OPERATOR_GEOLOOKUP} { BEGIN(TRANSACTION_FROM_OPERATOR_TO_ACTIONS); return p::make_OPERATOR_GEOLOOKUP(yytext, *driver.loc.back()); } {OPERATOR_GEOLOOKUP} { BEGIN(TRANSACTION_FROM_OPERATOR_TO_ACTIONS); return p::make_OPERATOR_GEOLOOKUP(yytext, *driver.loc.back()); }
@ -848,11 +861,8 @@ EQUALS_MINUS (?i:=\-)
[ ]{FREE_TEXT} { BEGIN(TRANSACTION_FROM_OPERATOR_TO_ACTIONS); return p::make_FREE_TEXT(yytext+1, *driver.loc.back()); } [ ]{FREE_TEXT} { BEGIN(TRANSACTION_FROM_OPERATOR_TO_ACTIONS); return p::make_FREE_TEXT(yytext+1, *driver.loc.back()); }
} }
<EXPECTING_VARIABLE>{
[|] { return p::make_PIPE(*driver.loc.back()); }
}
<INITIAL,EXPECTING_VARIABLE,EXPECTING_OPERATOR>{ <INITIAL,EXPECTING_OPERATOR>{
[ \t]+ { } [ \t]+ { }
[ \t]*\\\n[ \t]* { driver.loc.back()->lines(1); driver.loc.back()->step(); } [ \t]*\\\n[ \t]* { driver.loc.back()->lines(1); driver.loc.back()->step(); }
[ \t]*\\\r\n[ \t]* { driver.loc.back()->lines(1); driver.loc.back()->step(); } [ \t]*\\\r\n[ \t]* { driver.loc.back()->lines(1); driver.loc.back()->step(); }

View File

@ -417,11 +417,32 @@ std::list<std::pair<std::shared_ptr<std::string>,
std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars( 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::vector<Variable *> *variables = m_variables; std::list<const std::string*> exclusions_update_by_tag_remove;
std::vector<Variables::Variable *> variables;
std::vector<std::unique_ptr<collection::Variable>> finalVars; std::vector<std::unique_ptr<collection::Variable>> finalVars;
for (int i = 0; i < variables->size(); i++) { std::copy (m_variables->begin(), m_variables->end(), std::back_inserter(variables));
Variable *variable = variables->at(i);
for (auto &a : trans->m_rules->m_exceptions.m_variable_update_target_by_tag) {
if (containsTag(a.first, 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_tag_remove.push_back(y->m_key);
}
exclusions_update_by_tag_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++) {
Variable *variable = variables.at(i);
if (variable->m_isExclusion) { if (variable->m_isExclusion) {
std::vector<const collection::Variable *> z; std::vector<const collection::Variable *> z;
variable->evaluateInternal(trans, this, &z); variable->evaluateInternal(trans, this, &z);
@ -431,9 +452,8 @@ 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;
bool ignoreVariable = false; bool ignoreVariable = false;
@ -457,7 +477,20 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
} }
continue; continue;
} }
if (std::find_if(exclusions_update_by_tag_remove.begin(),
exclusions_update_by_tag_remove.end(),
[key](const std::string *m) -> bool { return *key == *m; })
!= exclusions_update_by_tag_remove.end()) {
#ifndef NO_LOGS
trans->debug(9, "Variable: " + *key +
" is part of the exclusion list (from update by tag), 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;
@ -519,6 +552,7 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
finalVars.push_back(std::move(var)); finalVars.push_back(std::move(var));
} }
} }
return finalVars; return finalVars;
} }

View File

@ -18,11 +18,30 @@
#include <string> #include <string>
#include "src/utils/string.h" #include "src/utils/string.h"
#include "src/variables/variable.h"
namespace modsecurity { namespace modsecurity {
RulesExceptions::RulesExceptions() {
}
RulesExceptions::~RulesExceptions() {
}
bool RulesExceptions::loadUpdateTargetByTag(const std::string &tag,
std::unique_ptr<std::vector<std::unique_ptr<Variables::Variable> > > var,
std::string *error) {
for (auto &i : *var) {
m_variable_update_target_by_tag.emplace(std::pair<std::string, std::unique_ptr<Variables::Variable>>(tag, 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, ' ');
@ -109,7 +128,7 @@ bool RulesExceptions::contains(int a) {
} }
bool RulesExceptions::merge(const RulesExceptions& from) { bool RulesExceptions::merge(RulesExceptions& from) {
for (int a : from.m_numbers) { for (int a : from.m_numbers) {
bool ret = addNumber(a); bool ret = addNumber(a);
if (ret == false) { if (ret == false) {
@ -123,9 +142,13 @@ bool RulesExceptions::merge(const RulesExceptions& from) {
} }
} }
for (auto &p : from.m_variable_update_target_by_tag) {
m_variable_update_target_by_tag.emplace(std::pair<std::string, std::unique_ptr<Variables::Variable>>(p.first, std::move(p.second)));
}
return true; return true;
} }
} // namespace modsecurity } // namespace modsecurity