Adds support the variable rule

Issue #1016
This commit is contained in:
Felipe Zimmerle 2016-06-20 13:52:45 -03:00
parent 45bfb594b9
commit 56d084a7f4
No known key found for this signature in database
GPG Key ID: E6DFB08CE8B11277
12 changed files with 415 additions and 6 deletions

View File

@ -217,3 +217,4 @@ TESTS+=test/test-cases/secrules-language-tests/operators/eq.json
TESTS+=test/test-cases/regression/variable-REQBODY_PROCESSOR.json
TESTS+=test/test-cases/regression/variable-REQBODY_PROCESSOR_ERROR.json
TESTS+=test/test-cases/regression/variable-URLENCODED_ERROR.json
TESTS+=test/test-cases/regression/variable-RULE.json

View File

@ -71,7 +71,8 @@ VARIABLES = \
variables/variable.cc \
variables/variations/count.cc \
variables/variations/exclusion.cc \
variables/xml.cc
variables/xml.cc \
variables/rule.cc
ACTIONS = \

View File

@ -29,13 +29,15 @@ namespace actions {
bool LogData::evaluate(Rule *rule, Transaction *transaction, RuleMessage *rm) {
std::string data = MacroExpansion::expand(m_parser_payload, transaction);
rm->m_data = data;
rm->m_data = data(transaction);
return true;
}
std::string LogData::data(Transaction *transaction) {
return MacroExpansion::expand(m_parser_payload, transaction);
}
} // namespace actions
} // namespace modsecurity

View File

@ -34,6 +34,8 @@ class LogData : public Action {
bool evaluate(Rule *rule, Transaction *transaction,
RuleMessage *rm) override;
std::string data(Transaction *Transaction);
};

View File

@ -53,11 +53,16 @@ bool Msg::evaluate(Rule *rule, Transaction *transaction) {
transaction->debug(9, "Saving msg: " + msg);
#endif
rule->m_log_message = msg;
rule->m_log_message = data(transaction);
return true;
}
std::string Msg::data(Transaction *transaction) {
return MacroExpansion::expand(m_parser_payload, transaction);
}
} // namespace actions
} // namespace modsecurity

View File

@ -33,6 +33,8 @@ class Msg : public Action {
: Action(action, RunTimeOnlyIfMatchKind) { }
bool evaluate(Rule *rule, Transaction *transaction) override;
std::string data(Transaction *Transaction);
};

View File

@ -38,7 +38,6 @@ class Severity : public Action {
RuleMessage *rm) override;
bool init(std::string *error);
private:
int m_severity;
};

View File

@ -65,6 +65,7 @@ class Driver;
#include "variables/time_year.h"
#include "variables/tx.h"
#include "variables/xml.h"
#include "variables/rule.h"
using modsecurity::ModSecurity;
@ -247,6 +248,7 @@ using modsecurity::Variables::XML;
%token <std::string> RUN_TIME_VAR_TIME_WDAY
%token <std::string> RUN_TIME_VAR_TIME_YEAR
%token <std::string> RUN_TIME_VAR_XML
%token <std::string> RUN_TIME_VAR_RULE
%token <std::string> CONFIG_SEC_REMOTE_RULES_FAIL_ACTION
@ -891,6 +893,17 @@ var:
if (!var) { var = new XML(name); }
$$ = var;
}
| RUN_TIME_VAR_RULE
{
std::string name($1);
CHECK_VARIATION_DECL
CHECK_VARIATION(&) { var = new Count(
new modsecurity::Variables::Rule(name)); }
CHECK_VARIATION(!) { var = new Exclusion(
new modsecurity::Variables::Rule(name)); }
if (!var) { var = new modsecurity::Variables::Rule(name); }
$$ = var;
}
;
act:

View File

@ -148,6 +148,7 @@ RUN_TIME_VAR_TIME_SEC (?i:TIME_SEC)
RUN_TIME_VAR_TIME_WDAY (?i:TIME_WDAY)
RUN_TIME_VAR_TIME_YEAR (?i:TIME_YEAR)
RUN_TIME_VAR_XML (?i:XML)
RUN_TIME_VAR_RULE (?i:RULE)
VARIABLENOCOLON (?i:URLENCODED_ERROR|REQBODY_PROCESSOR_ERROR_MSG|REQBODY_PROCESSOR_ERROR|REQBODY_PROCESSOR|REQBODY_ERROR_MSG|REQBODY_ERROR|MULTIPART_FILE_LIMIT_EXCEEDED|MULTIPART_INVALID_QUOTING|MULTIPART_HEADER_FOLDING|MULTIPART_INVALID_HEADER_FOLDING|MULTIPART_STRICT_ERROR|MULTIPART_UNMATCHED_BOUNDARY|REMOTE_ADDR|REQUEST_LINE)
@ -248,6 +249,8 @@ CONFIG_DIR_UNICODE_MAP_FILE (?i:SecUnicodeMapFile)
[!&]?{VARIABLE_COL}(\:[\']{FREE_TEXT_QUOTE}[\'])? { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_VARIABLE_COL(yytext, *driver.loc.back()); }
[!&]?{RUN_TIME_VAR_XML}(\:{DICT_ELEMENT})? { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_RUN_TIME_VAR_XML(yytext, *driver.loc.back()); }
[!&]?{RUN_TIME_VAR_XML}(\:[\']{FREE_TEXT_QUOTE}[\'])? { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_RUN_TIME_VAR_XML(yytext, *driver.loc.back()); }
[!&]?{RUN_TIME_VAR_RULE}(\:{DICT_ELEMENT})? { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_RUN_TIME_VAR_RULE(yytext, *driver.loc.back()); }
[!&]?{RUN_TIME_VAR_RULE}(\:[\']{FREE_TEXT_QUOTE}[\'])? { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_RUN_TIME_VAR_RULE(yytext, *driver.loc.back()); }
[!&]?{VARIABLE_TX}(\:{DICT_ELEMENT})? { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_VARIABLE_TX(yytext, *driver.loc.back()); }
[!&]?{VARIABLE_TX}(\:[\']{FREE_TEXT_QUOTE}[\'])? { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_VARIABLE_TX(yytext, *driver.loc.back()); }
[!&]?{RUN_TIME_VAR_DUR} { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_RUN_TIME_VAR_DUR(yytext, *driver.loc.back()); }
@ -267,6 +270,8 @@ CONFIG_DIR_UNICODE_MAP_FILE (?i:SecUnicodeMapFile)
["][!&]?{VARIABLE_COL}(\:[\']{FREE_TEXT_QUOTE}[\'])?["] { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_VARIABLE_COL(yytext, *driver.loc.back()); }
["][!&]?{RUN_TIME_VAR_XML}(\:{DICT_ELEMENT})? { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_RUN_TIME_VAR_XML(yytext, *driver.loc.back()); }
["][!&]?{RUN_TIME_VAR_XML}(\:[\']{FREE_TEXT_QUOTE}[\'])?["] { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_RUN_TIME_VAR_XML(yytext, *driver.loc.back()); }
["][!&]?{RUN_TIME_VAR_RULE}(\:{DICT_ELEMENT})? { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_RUN_TIME_VAR_RULE(yytext, *driver.loc.back()); }
["][!&]?{RUN_TIME_VAR_RULE}(\:[\']{FREE_TEXT_QUOTE}[\'])?["] { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_RUN_TIME_VAR_RULE(yytext, *driver.loc.back()); }
["][!&]?{RUN_TIME_VAR_DUR}["] { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_RUN_TIME_VAR_DUR(yytext, *driver.loc.back()); }
["][!&]?{RUN_TIME_VAR_ENV}(\:{DICT_ELEMENT})?["] { BEGIN(EXPECTING_OPERATOR); return yy::seclang_parser::make_RUN_TIME_VAR_ENV(yytext, *driver.loc.back()); }

103
src/variables/rule.cc Normal file
View File

@ -0,0 +1,103 @@
/*
* 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 "variables/rule.h"
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <libxml/xmlschemas.h>
#include <libxml/xpath.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/xpathInternals.h>
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <utility>
#include "modsecurity/transaction.h"
#include "modsecurity/rules_properties.h"
#include "modsecurity/rules.h"
#include "src/request_body_processor/xml.h"
#include "src/actions/action.h"
#include "src/actions/severity.h"
#include "src/actions/xmlns.h"
#include "src/actions/log_data.h"
#include "src/actions/msg.h"
namespace modsecurity {
namespace Variables {
void Rule::evaluateInternal(Transaction *t,
modsecurity::Rule *rule,
std::vector<const collection::Variable *> *l) {
std::map<std::string, std::string> envs;
// id
envs.insert(std::pair<std::string, std::string>("RULE:id",
std::to_string(rule->rule_id)));
// rev
envs.insert(std::pair<std::string, std::string>("RULE:rev",
rule->m_rev));
// severity
std::vector<actions::Action *> acts = rule->getActionsByName("severity");
for (actions::Action *i : acts) {
actions::Severity *a = reinterpret_cast<actions::Severity *>(i);
if (a) {
envs.insert(std::pair<std::string, std::string>("RULE:severity",
std::to_string(a->m_severity)));
}
}
// logdata
acts = rule->getActionsByName("logdata");
for (actions::Action *i : acts) {
actions::LogData *a = reinterpret_cast<actions::LogData *>(i);
if (a) {
envs.insert(std::pair<std::string, std::string>("RULE:logdata",
a->data(t)));
}
}
// msg
acts = rule->getActionsByName("msg");
for (actions::Action *i : acts) {
actions::Msg *a = reinterpret_cast<actions::Msg *>(i);
if (a) {
envs.insert(std::pair<std::string, std::string>("RULE:msg",
a->data(t)));
}
}
for (auto& x : envs) {
if ((x.first.substr(0, m_name.size() + 1).compare(m_name + ":") != 0)
&& (x.first != m_name)) {
continue;
}
l->push_back(new collection::Variable(x.first, x.second));
}
}
} // namespace Variables
} // namespace modsecurity

43
src/variables/rule.h Normal file
View File

@ -0,0 +1,43 @@
/*
* 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 <string>
#include <vector>
#include <list>
#ifndef SRC_VARIABLES_RULE_H_
#define SRC_VARIABLES_RULE_H_
#include "variables/variable.h"
namespace modsecurity {
class Transaction;
namespace Variables {
class Rule : public Variable {
public:
explicit Rule(std::string _name)
: Variable(_name) { };
void evaluateInternal(Transaction *transaction,
modsecurity::Rule *rule,
std::vector<const collection::Variable *> *l) override;
};
} // namespace Variables
} // namespace modsecurity
#endif // SRC_VARIABLES_RULE_H_

View File

@ -0,0 +1,233 @@
[
{
"enabled":1,
"version_min":300000,
"title":"Testing Variables :: RULE (1/5)",
"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":"/",
"method":"POST",
"body": [
"param1=value1&param2=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":"Target value: \"1\" \\(Variable: RULE:id\\)"
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"SecRule RULE:id \"@contains test\" \"id:1,phase:3,rev:1.3,pass,t:trim\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing Variables :: RULE (2/5)",
"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":"/",
"method":"POST",
"body": [
"param1=value1&param2=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":"Target value: \"200\" \\(Variable: RULE:rev\\)"
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"SecRule RULE:rev \"@contains test\" \"id:1,rev:200,phase:3,pass,t:trim\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing Variables :: RULE (3/5)",
"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":"/",
"method":"POST",
"body": [
"param1=value1&param2=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":"Target value: \"2\" \\(Variable: RULE:severity\\)"
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"SecRule RULE:severity \"@contains test\" \"id:1,phase:3,severity:critical,pass,t:trim\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing Variables :: RULE (4/5)",
"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":"/",
"method":"POST",
"body": [
"param1=value1&param2=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":"Target value: \"data123\" \\(Variable: RULE:logdata\\)"
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"SecRule RULE:logdata \"@contains test\" \"id:1,logdata:'data123',phase:3,pass,t:trim\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing Variables :: RULE (5/5)",
"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":"/",
"method":"POST",
"body": [
"param1=value1&param2=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":" Target value: \"message123\" \\(Variable: RULE:msg\\)"
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"SecRule RULE:msg \"@contains test\" \"id:1,msg:'message123',phase:3,pass,t:trim\""
]
}
]