diff --git a/src/Makefile.am b/src/Makefile.am index 40db6522..5efceed0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -95,6 +95,7 @@ libmodsecurity_la_SOURCES = \ unique_id.cc \ variable.cc \ variable_duration.cc \ + variable_env.cc \ operators/operator.cc \ operators/detect_sqli.cc \ operators/detect_xss.cc \ diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index 91f925ae..0000ca56 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -16,12 +16,14 @@ class Driver; #include "operators/operator.h" #include "rule.h" #include "variable_duration.h" +#include "variable_env.h" using ModSecurity::actions::Action; using ModSecurity::actions::transformations::Transformation; using ModSecurity::operators::Operator; using ModSecurity::Variable; using ModSecurity::VariableDuration; +using ModSecurity::VariableEnv; using ModSecurity::Rule; } @@ -81,10 +83,12 @@ using ModSecurity::Rule; %token CONFIG_DIR_DEBUG_LOG %token CONFIG_DIR_DEBUG_LVL -%token OPERATOR -%token ACTION %token VARIABLE %token RUN_TIME_VAR_DUR +%token RUN_TIME_VAR_ENV + +%token OPERATOR +%token ACTION %token TRANSFORMATION %token CONFIG_VALUE_NUMBER @@ -257,6 +261,18 @@ variables: variables->push_back(new VariableDuration($1)); $$ = variables; } + | variables PIPE RUN_TIME_VAR_ENV + { + std::vector *v = $1; + v->push_back(new VariableEnv($3)); + $$ = $1; + } + | RUN_TIME_VAR_ENV + { + std::vector *variables = new std::vector; + variables->push_back(new VariableEnv($1)); + $$ = variables; + } actions: actions COMMA SPACE ACTION diff --git a/src/parser/seclang-scanner.ll b/src/parser/seclang-scanner.ll index b2718a21..19d088bc 100755 --- a/src/parser/seclang-scanner.ll +++ b/src/parser/seclang-scanner.ll @@ -58,6 +58,7 @@ TRANSFORMATION t:(lowercase|urlDecodeUni|urlDecode|none|compressWhitespace|remo 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) +RUN_TIME_VAR_ENV (?i:ENV) VARIABLENOCOLON (?i:REQBODY_ERROR|MULTIPART_STRICT_ERROR|MULTIPART_UNMATCHED_BOUNDARY|REMOTE_ADDR|REQUEST_LINE) @@ -107,6 +108,12 @@ FREE_TEXT [^\"]+ {CONFIG_DIR_DEBUG_LOG}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_DEBUG_LOG(strchr(yytext, ' ') + 1, loc); } {CONFIG_DIR_DEBUG_LVL}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_DEBUG_LVL(strchr(yytext, ' ') + 1, loc); } +%{ /* Variables */ %} +{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); } +{RUN_TIME_VAR_ENV}:?{DICT_ELEMENT}? { return yy::seclang_parser::make_RUN_TIME_VAR_ENV(yytext, loc); } + + {CONFIG_COMPONENT_SIG}[ ]["]{FREE_TEXT}["] { return yy::seclang_parser::make_CONFIG_COMPONENT_SIG(strchr(yytext, ' ') + 2, loc); } {CONFIG_VALUE_ON} { return yy::seclang_parser::make_CONFIG_VALUE_ON(yytext, loc); } @@ -121,8 +128,6 @@ FREE_TEXT [^\"]+ ["] { return yy::seclang_parser::make_QUOTATION_MARK(loc); } [,] { 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/variable_env.cc b/src/variable_env.cc new file mode 100644 index 00000000..06261419 --- /dev/null +++ b/src/variable_env.cc @@ -0,0 +1,67 @@ +/** + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include "src/variable_env.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "modsecurity/assay.h" +#include "src/utils.h" + +extern char **environ; + +namespace ModSecurity { + +std::list> + VariableEnv::evaluate(Assay *assay) { + std::list> resl; + + std::map envs; + for (char **current = environ; *current; current++) { + std::string env = std::string(*current); + std::vector key_value = split(env, '='); + envs.insert(std::pair("ENV:" + key_value[0], + key_value[1])); + if ("env:" + key_value[0] == name) { + std::pair pair; + pair = std::make_pair(name, key_value[1]); + resl.push_back(pair); + return resl; + } + } + + for (auto& x : envs) { + if ((x.first.substr(0, name.size() + 1).compare(name + ":") != 0) + && (x.first != name)) { + continue; + } + std::pair pair; + pair = std::make_pair(x.first, x.second); + resl.push_back(pair); + } + + return resl; +} + + +} // namespace ModSecurity diff --git a/src/variable_env.h b/src/variable_env.h new file mode 100644 index 00000000..1be999b3 --- /dev/null +++ b/src/variable_env.h @@ -0,0 +1,41 @@ +/** + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include +#include +#include +#include + +#ifndef SRC_VARIABLE_ENV_H_ +#define SRC_VARIABLE_ENV_H_ + +#include "src/variable.h" + +namespace ModSecurity { + +class Assay; + +class VariableEnv : public Variable { + public: + explicit VariableEnv(std::string _name) + : Variable(_name) { } + + std::list> + evaluate(Assay *assay) override; +}; + +} // namespace ModSecurity + +#endif // SRC_VARIABLE_ENV_H_ diff --git a/test/test-cases/regression/variable-ENV.json b/test/test-cases/regression/variable-ENV.json new file mode 100644 index 00000000..7d58acc5 --- /dev/null +++ b/test/test-cases/regression/variable-ENV.json @@ -0,0 +1,141 @@ +[ + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: ENV (1/3)", + "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":"*/*", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/", + "protocol":"POST", + "body": [ + "param1=value1¶m2=value2" + ] + }, + "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":"Variable: ENV:PATH" + }, + "rules":[ + "SecRuleEngine On", + "SecDebugLog \/tmp\/modsec_debug.log", + "SecDebugLogLevel 9", + "SecRule ENV:PATH \"@contains test\" \"phase:3,pass,t:trim\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: ENV (2/3)", + "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":"*/*", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/", + "protocol":"POST", + "body": [ + "param1=value1¶m2=value2" + ] + }, + "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":"Variable: ENV:TERM" + }, + "rules":[ + "SecRuleEngine On", + "SecDebugLog \/tmp\/modsec_debug.log", + "SecDebugLogLevel 9", + "SecRule ENV:TERM \"@contains test\" \"phase:3,pass,t:trim\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: ENV (3/3)", + "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":"*/*", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/", + "protocol":"POST", + "body": [ + "param1=value1¶m2=value2" + ] + }, + "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":"Variable: ENV:PATH" + }, + "rules":[ + "SecRuleEngine On", + "SecDebugLog \/tmp\/modsec_debug.log", + "SecDebugLogLevel 9", + "SecRule ENV \"@contains test\" \"phase:3,pass,t:trim\"" + ] + } +] +