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 <utility>
#include <vector>
#include <memory>
#endif
#ifndef HEADERS_MODSECURITY_RULES_EXCEPTIONS_H_
@ -34,15 +35,26 @@
namespace modsecurity {
namespace Variables {
class Variable;
}
class RulesExceptions {
public:
RulesExceptions() { }
RulesExceptions();
~RulesExceptions();
bool load(const std::string &data, std::string *error);
bool addRange(int a, int b);
bool addNumber(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:
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_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_UPDATE_TARGET_BY_TAG "CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG"
CONFIG_UPDLOAD_KEEP_FILES "CONFIG_UPDLOAD_KEEP_FILES"
CONFIG_UPDLOAD_SAVE_TMP_FILES "CONFIG_UPDLOAD_SAVE_TMP_FILES"
CONFIG_UPLOAD_DIR "CONFIG_UPLOAD_DIR"
@ -1172,6 +1173,19 @@ expression:
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 */
| 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;
typedef yy::seclang_parser p;
static int state_variable_from = 0;
// Work around an incompatibility in flex (at least versions
// 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_FAIL_ACTION (?i:SecRemoteRulesFailAction)
CONFIG_SEC_REMOVE_RULES_BY_ID (?i:SecRuleRemoveById)
CONFIG_SEC_UPDATE_TARGET_BY_TAG (?i:SecRuleUpdateTargetByTag)
CONFIG_UPDLOAD_KEEP_FILES (?i:SecUploadKeepFiles)
CONFIG_UPDLOAD_SAVE_TMP_FILES (?i:SecTmpSaveUploadedFiles)
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_STATUS_ENGINE (?i:SecStatusEngine)
CONGIG_DIR_SEC_TMP_DIR (?i:SecTmpDir)
DICT_ELEMENT ([^\"| \t]|([^\\]\\\"))+
DICT_ELEMENT ([^\"|,\n \t]|([^\\]\\\"))+
DICT_ELEMENT_WITH_PIPE [^ \t"]+
@ -347,7 +349,6 @@ EQUALS_MINUS (?i:=\-)
%x TRANSACTION_TO_VARIABLE
%x EXPECTING_VARIABLE
%x TRANSACTION_FROM_VARIABLE_TO_OPERATOR
%x EXPECTING_OPERATOR
%x COMMENT
%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_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_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_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()); }
@ -629,6 +632,7 @@ EQUALS_MINUS (?i:=\-)
<TRANSACTION_TO_VARIABLE>{
[ \t]* { BEGIN(EXPECTING_VARIABLE); }
[ \t]*\"[ \t]* { BEGIN(EXPECTING_VARIABLE); }
}
<TRANSACTION_FROM_DIRECTIVE_TO_ACTIONS>{
@ -640,6 +644,16 @@ EQUALS_MINUS (?i:=\-)
<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_GET_NAMES} { return p::make_VARIABLE_ARGS_GET_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 - 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_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); }
["] { 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>{
{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()); }
}
<EXPECTING_VARIABLE>{
[|] { return p::make_PIPE(*driver.loc.back()); }
}
<INITIAL,EXPECTING_VARIABLE,EXPECTING_OPERATOR>{
<INITIAL,EXPECTING_OPERATOR>{
[ \t]+ { }
[ \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(); }

View File

@ -417,11 +417,32 @@ std::list<std::pair<std::shared_ptr<std::string>,
std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
Transaction *trans) {
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;
for (int i = 0; i < variables->size(); i++) {
Variable *variable = variables->at(i);
std::copy (m_variables->begin(), m_variables->end(), std::back_inserter(variables));
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) {
std::vector<const collection::Variable *> 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);
}
}
for (int i = 0; i < variables->size(); i++) {
Variable *variable = variables->at(i);
for (int i = 0; i < variables.size(); i++) {
Variable *variable = variables.at(i);
std::vector<const collection::Variable *> e;
bool ignoreVariable = false;
@ -457,7 +477,20 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
}
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) {
std::string tag = i.first;
std::string args = i.second;
@ -519,6 +552,7 @@ std::vector<std::unique_ptr<collection::Variable>> Rule::getFinalVars(
finalVars.push_back(std::move(var));
}
}
return finalVars;
}

View File

@ -18,11 +18,30 @@
#include <string>
#include "src/utils/string.h"
#include "src/variables/variable.h"
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 added = false;
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) {
bool ret = addNumber(a);
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;
}
} // namespace modsecurity