From 33dff0f1bf4c8cdd4eb23860d6839d851861e2ab Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Tue, 14 Jul 2015 19:15:54 -0300 Subject: [PATCH] Refactoring on the variables resoluvtion method --- headers/modsecurity/assay.h | 6 +- src/assay.cc | 27 +++++++-- src/parser/seclang-parser.yy | 23 ++++++-- src/parser/seclang-scanner.ll | 4 +- src/rule.cc | 100 ++++++++++++++-------------------- src/rule.h | 4 +- src/variable.cc | 7 ++- src/variable.h | 6 +- 8 files changed, 100 insertions(+), 77 deletions(-) diff --git a/headers/modsecurity/assay.h b/headers/modsecurity/assay.h index 3cce74d6..073c5927 100644 --- a/headers/modsecurity/assay.h +++ b/headers/modsecurity/assay.h @@ -24,6 +24,8 @@ #include #include #include +#include +#include #endif #include @@ -136,7 +138,8 @@ class Assay { const char *getResponseBody(); int getResponseBodyLenth(); - std::list resolve_variable(std::string var); + std::list> + resolve_variable(std::string var); std::string* resolve_variable_first(std::string); void store_variable(std::string, const std::string &value); @@ -158,6 +161,7 @@ class Assay { std::string id; time_t timeStamp; + std::chrono::system_clock::time_point start; private: std::ofstream myfile; diff --git a/src/assay.cc b/src/assay.cc index 99577023..048239f9 100644 --- a/src/assay.cc +++ b/src/assay.cc @@ -1064,13 +1064,32 @@ void Assay::store_variable(std::string key, const std::string &value) { } -std::list Assay::resolve_variable(std::string var) { - std::list l; +std::list> + Assay::resolve_variable(std::string var) { + std::list> l; + std::pair pair; + auto range = m_variables_strings.equal_range(var); for (auto it = range.first; it != range.second; ++it) { - std::cout << it->first << ' ' << it->second << '\n'; - l.push_back(it->second); + pair = std::make_pair(std::string(var), std::string(it->second)); + l.push_back(pair); + } + + if (l.size() == 0) { + for (auto& x : m_variables_strings) { + if ((x.first.substr(0, var.size() + 1).compare(var + ":") != 0) + && (x.first != var)) { + continue; + } + std::list> t; + t = resolve_variable(x.first); + for (std::pair z : t) { + pair = std::make_pair(std::string(z.first), + std::string(z.second)); + l.push_back(pair); + } + } } return l; diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index ecad1b4b..28156d61 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -82,12 +82,13 @@ using ModSecurity::Rule; %token OPERATOR %token ACTION %token VARIABLE +%token RUN_TIME_VAR_DUR %token TRANSFORMATION %token CONFIG_VALUE_NUMBER %type *> actions -%type *> variables +%type *> variables %printer { yyoutput << $$; } <*>; %% @@ -232,14 +233,26 @@ expression: variables: variables PIPE VARIABLE { - std::vector *v = $1; - v->push_back(Variable($3)); + std::vector *v = $1; + v->push_back(new Variable($3)); $$ = $1; } | VARIABLE { - std::vector *variables = new std::vector; - variables->push_back(Variable($1)); + std::vector *variables = new std::vector; + variables->push_back(new Variable($1)); + $$ = variables; + } + | variables PIPE RUN_TIME_VAR_DUR + { + std::vector *v = $1; + v->push_back(new Variable($3)); + $$ = $1; + } + | RUN_TIME_VAR_DUR + { + std::vector *variables = new std::vector; + variables->push_back(new Variable($1)); $$ = variables; } diff --git a/src/parser/seclang-scanner.ll b/src/parser/seclang-scanner.ll index b73c6d1a..b2718a21 100755 --- a/src/parser/seclang-scanner.ll +++ b/src/parser/seclang-scanner.ll @@ -56,7 +56,8 @@ OPERATORNOARG (?i:@detectSQLi|@detectXSS|@geoLookup|@validateUrlEncoding|@valida TRANSFORMATION t:(lowercase|urlDecodeUni|urlDecode|none|compressWhitespace|removeWhitespace|replaceNulls|removeNulls|htmlEntityDecode|jsDecode|cssDecode|trim) -VARIABLE (?i:AUTH_TYPE|ARGS_NAMES|ARGS|QUERY_STRING|REMOTE_ADDR|REQUEST_BASENAME|REQUEST_BODY|REQUEST_COOKIES_NAMES|REQUEST_COOKIES|REQUEST_FILENAME|REQUEST_HEADERS_NAMES|REQUEST_HEADERS|REQUEST_METHOD|REQUEST_PROTOCOL|REQUEST_URI|RESPONSE_BODY|RESPONSE_CONTENT_LENGTH|RESPONSE_CONTENT_TYPE|RESPONSE_HEADERS_NAMES|RESPONSE_HEADERS|RESPONSE_PROTOCOL|RESPONSE_STATUS|TX) +VARIABLE (?i:AUTH_TYPE|ARGS_NAMES|ARGS|QUERY_STRING|REMOTE_ADDR|REQUEST_BASENAME|REQUEST_BODY|REQUEST_COOKIES_NAMES|REQUEST_COOKIES|REQUEST_FILENAME|REQUEST_HEADERS_NAMES|REQUEST_HEADERS|REQUEST_METHOD|REQUEST_PROTOCOL|REQUEST_URI|RESPONSE_BODY|RESPONSE_CONTENT_LENGTH|RESPONSE_CONTENT_TYPE|RESPONSE_HEADERS_NAMES|RESPONSE_HEADERS|RESPONSE_PROTOCOL|RESPONSE_STATUS|TX) +RUN_TIME_VAR_DUR (?i:DURATION) VARIABLENOCOLON (?i:REQBODY_ERROR|MULTIPART_STRICT_ERROR|MULTIPART_UNMATCHED_BOUNDARY|REMOTE_ADDR|REQUEST_LINE) @@ -121,6 +122,7 @@ FREE_TEXT [^\"]+ [,] { return yy::seclang_parser::make_COMMA(loc); } [|] { return yy::seclang_parser::make_PIPE(loc); } {VARIABLE}:?{DICT_ELEMENT}? { return yy::seclang_parser::make_VARIABLE(yytext, loc); } +{RUN_TIME_VAR_DUR} { return yy::seclang_parser::make_RUN_TIME_VAR_DUR(yytext, loc); } {VARIABLENOCOLON} { return yy::seclang_parser::make_VARIABLE(yytext, loc); } [ \t]+ { return yy::seclang_parser::make_SPACE(loc); } \n { return yy::seclang_parser::make_NEW_LINE(loc); } diff --git a/src/rule.cc b/src/rule.cc index 67edd6b5..aa80fd71 100644 --- a/src/rule.cc +++ b/src/rule.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include "operators/operator.h" #include "actions/action.h" @@ -33,7 +34,7 @@ using operators::Operator; using actions::Action; Rule::Rule(Operator *_op, - std::vector *_variables, + std::vector *_variables, std::vector *_actions) : variables(_variables), op(_op), @@ -63,78 +64,59 @@ Rule::Rule(Operator *_op, } bool Rule::evaluate(Assay *assay) { - std::vector *variables = this->variables; + bool ret = false; + std::vector *variables = this->variables; assay->debug(4, "Executing operator \"" + this->op->op \ + "\" with param \"" + this->op->param + "\" against " \ + Variable::to_s(variables) + "."); + clock_t begin = clock(); + for (int i = 0; i < variables->size(); i++) { - Variable variable = variables->at(i); + int transformations = 0; + Variable *variable = variables->at(i); - if (std::strchr(variable.name.c_str(), ':') == NULL) { - for (auto& x : assay->m_variables_strings) { - if ((x.first.substr(0, variable.name.size() + 1).compare( \ - variable.name + ":") != 0) && (x.first != variable.name)) { - continue; - } + std::list> e = + variable->evaluate(assay); - int transformations = 0; - std::string value = x.second; + for (auto &v : e) { + std::string value = v.second; + for (Action *a : + this->actions_runtime_pre) { + value = a->evaluate(value, assay); + assay->debug(9, " T (" + \ + std::to_string(transformations) + ") " + \ + a->name + ": \"" + value +"\""); + transformations++; + } + + assay->debug(9, "Target value: \"" + value + "\" (Variable: " + \ + v.first + ")"); + + ret = this->op->evaluate(assay, value); + + clock_t end = clock(); + double elapsed_secs = static_cast(end - begin) \ + / CLOCKS_PER_SEC; + + assay->debug(4, "Operator completed in " + \ + std::to_string(elapsed_secs) + " seconds"); + + if (ret) { + assay->debug(4, "Rule returned 1."); for (Action *a : - this->actions_runtime_pre) { - value = a->evaluate(value, assay); - assay->debug(9, " T (" + \ - std::to_string(transformations) + ") " + \ - a->name + ": \"" + value +"\""); - - transformations++; - } - - assay->debug(9, "Target value: \"" + value + "\""); - clock_t begin = clock(); - - bool ret = this->op->evaluate(assay, value); - - clock_t end = clock(); - double elapsed_secs = static_cast(end - begin) \ - / CLOCKS_PER_SEC; - - assay->debug(4, "Operator completed in " + \ - std::to_string(elapsed_secs) + " seconds"); - - if (ret) { - assay->debug(4, "Rule returned 1."); - - for (Action *a : - this->actions_runtime_pos) { - assay->debug(4, "Running action: " + a->action); - a->evaluate(assay); - } - - return ret; - } else { - assay->debug(4, "Rule returned 0."); + this->actions_runtime_pos) { + assay->debug(4, "Running action: " + a->action); + a->evaluate(assay); } + } else { + assay->debug(4, "Rule returned 0."); } - } else { - bool ret = false; - try { - std::list e = assay->resolve_variable( - variable.name); - for (std::string value : e) { - ret = this->op->evaluate(assay, - value); - } - } catch (...) { - } - - return ret; } - - return false; } + return ret; } } // namespace ModSecurity diff --git a/src/rule.h b/src/rule.h index 42ef77da..c027fd27 100644 --- a/src/rule.h +++ b/src/rule.h @@ -31,7 +31,7 @@ namespace ModSecurity { class Rule { public: Rule(operators::Operator *_op, - std::vector *_variables, + std::vector *_variables, std::vector *_actions); bool evaluate(Assay *assay); @@ -41,7 +41,7 @@ class Rule { std::vector actions_runtime_pre; std::vector actions_runtime_pos; - std::vector *variables; + std::vector *variables; int phase; double rule_id; }; diff --git a/src/variable.cc b/src/variable.cc index 4ee925ad..09e079b6 100644 --- a/src/variable.cc +++ b/src/variable.cc @@ -24,15 +24,16 @@ namespace ModSecurity { -std::list Variable::evaluate(Assay *assay) { +std::list> + Variable::evaluate(Assay *assay) { return assay->resolve_variable(this->name); } std::string Variable::to_s( - std::vector *variables) { + std::vector *variables) { std::string ret; for (int i = 0; i < variables->size() ; i++) { - std::string name = variables->at(i).name; + std::string name = variables->at(i)->name; if (i == 0) { ret = ret + name; diff --git a/src/variable.h b/src/variable.h index f7f6f4eb..a6340e6e 100644 --- a/src/variable.h +++ b/src/variable.h @@ -16,6 +16,7 @@ #include #include #include +#include #ifndef SRC_VARIABLE_H_ #define SRC_VARIABLE_H_ @@ -29,8 +30,9 @@ class Variable { explicit Variable(std::string _name) : name(_name) { } - static std::string to_s(std::vector *variables); - std::list evaluate(Assay *assay); + static std::string to_s(std::vector *variables); + virtual std::list> + evaluate(Assay *assay); std::string name; };