mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 05:45:59 +03:00
Adds initial support to SecRuleUpdateTargetByTag
This commit is contained in:
parent
65bd06fb7f
commit
fba9c20ea1
@ -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
@ -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
@ -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(); }
|
||||
|
48
src/rule.cc
48
src/rule.cc
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user