Adds support to unconditional rules

This commit is contained in:
Felipe Zimmerle 2015-09-04 14:52:18 -03:00
parent 4e8bb276b8
commit b048794f4e
7 changed files with 168 additions and 1 deletions

View File

@ -39,6 +39,17 @@ Driver::~Driver() {
delete loc.back();
}
int Driver::addSecAction(Rule *rule) {
if (rule->phase >= ModSecurity::Phases::NUMBER_OF_PHASES) {
parserError << "Unknown phase: " << std::to_string(rule->phase);
parserError << std::endl;
return false;
}
rules[rule->phase].push_back(rule);
return true;
}
int Driver::addSecRule(Rule *rule) {
if (rule->phase >= ModSecurity::Phases::NUMBER_OF_PHASES) {

View File

@ -57,6 +57,7 @@ class Driver : public RulesProperties {
virtual ~Driver();
int addSecRule(Rule *rule);
int addSecAction(Rule *rule);
int result;

View File

@ -190,6 +190,7 @@ using ModSecurity::Variables::Variable;
%token <std::string> CONFIG_DIR_DEBUG_LOG
%token <std::string> CONFIG_DIR_DEBUG_LVL
%token <std::string> CONFIG_DIR_SEC_ACTION
%token <std::string> CONFIG_DIR_SEC_DEFAULT_ACTION
%token <std::string> VARIABLE
@ -356,6 +357,24 @@ expression:
);
driver.addSecRule(rule);
}
| CONFIG_DIR_SEC_ACTION SPACE QUOTATION_MARK actions QUOTATION_MARK
{
Rule *rule = new Rule(
/* op */ NULL,
/* variables */ NULL,
/* actions */ $4
);
driver.addSecAction(rule);
}
| CONFIG_DIR_SEC_ACTION SPACE actions
{
Rule *rule = new Rule(
/* op */ NULL,
/* variables */ NULL,
/* actions */ $3
);
driver.addSecAction(rule);
}
| CONFIG_DIR_SEC_DEFAULT_ACTION SPACE QUOTATION_MARK actions QUOTATION_MARK
{
std::vector<Action *> *actions = $4;

View File

@ -39,6 +39,7 @@ DIRECTIVE (?i:SecRule)
LOG_DATA (?i:logdata)
CONFIG_DIR_SEC_DEFAULT_ACTION (?i:SecDefaultAction)
CONFIG_DIR_SEC_ACTION (?i:SecAction)
CONFIG_DIR_PCRE_MATCH_LIMIT_RECURSION (?i:SecPcreMatchLimitRecursion)
CONFIG_DIR_PCRE_MATCH_LIMIT (?i:SecPcreMatchLimit)
@ -243,6 +244,7 @@ CONFIG_DIR_UNICODE_MAP_FILE (?i:SecUnicodeMapFile)
{CONFIG_VALUE_PROCESS_PARTIAL} { return yy::seclang_parser::make_CONFIG_VALUE_PROCESS_PARTIAL(yytext, *driver.loc.back()); }
{CONFIG_VALUE_REJECT} { return yy::seclang_parser::make_CONFIG_VALUE_REJECT(yytext, *driver.loc.back()); }
{CONFIG_DIR_SEC_ACTION} { return yy::seclang_parser::make_CONFIG_DIR_SEC_ACTION(yytext, *driver.loc.back()); }
{CONFIG_DIR_SEC_DEFAULT_ACTION} { return yy::seclang_parser::make_CONFIG_DIR_SEC_DEFAULT_ACTION(yytext, *driver.loc.back()); }
<EXPECTING_OPERATOR>{

View File

@ -56,7 +56,7 @@ Rule::~Rule() {
actions_runtime_pos.pop_back();
delete a;
}
while (variables->empty() == false) {
while (variables != NULL && variables->empty() == false) {
auto *a = variables->back();
variables->pop_back();
delete a;
@ -75,6 +75,7 @@ Rule::Rule(Operator *_op,
op(_op),
rule_id(0),
phase(-1),
m_unconditional(false),
m_referenceCount(0) {
for (Action *a : *actions) {
if (a->action_kind == Action::ConfigurationKind) {
@ -98,13 +99,81 @@ Rule::Rule(Operator *_op,
phase = ModSecurity::Phases::RequestHeadersPhase;
}
if (op == NULL) {
m_unconditional = true;
}
delete actions;
}
bool Rule::evaluateActions(Assay *assay) {
int none = 0;
int transformations = 0;
for (Action *a : this->actions_runtime_pre) {
None *z = dynamic_cast<None *>(a);
if (z != NULL) {
none++;
}
}
assay->debug(4, "Running unconditional rule.");
if (none == 0) {
/*
for (Action *a : assay->m_rules->defaultActions[this->phase]) {
if (a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) {
value = a->evaluate(value, assay);
assay->debug(9, "(SecDefaultAction) T (" + \
std::to_string(transformations) + ") " + \
a->name + ": \"" + value +"\"");
transformations++;
}
}
*/
}
for (Action *a : this->actions_runtime_pre) {
None *z = dynamic_cast<None *>(a);
/*
if (none == 0) {
value = a->evaluate(value, assay);
assay->debug(9, " T (" + \
std::to_string(transformations) + ") " + \
a->name + ": \"" + value +"\"");
transformations++;
}
*/
if (z != NULL) {
none--;
}
}
for (Action *a : assay->m_rules->defaultActions[this->phase]) {
if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind) {
assay->debug(4, "(SecDefaultAction) Running action: " + a->action);
a->evaluate(this, assay);
}
}
for (Action *a :
this->actions_runtime_pos) {
assay->debug(4, "Running action: " + a->action);
a->evaluate(this, assay);
}
return true;
}
bool Rule::evaluate(Assay *assay) {
bool ret = false;
std::vector<Variable *> *variables = this->variables;
if (m_unconditional == true) {
return evaluateActions(assay);
}
assay->debug(4, "Executing operator \"" + this->op->op \
+ "\" with param \"" + this->op->param + "\" against " \
+ Variable::to_s(variables) + ".");

View File

@ -37,6 +37,7 @@ class Rule {
~Rule();
bool evaluate(Assay *assay);
bool evaluateActions(Assay *assay);
operators::Operator *op;
std::vector<actions::Action *> actions_conf;
@ -64,6 +65,7 @@ class Rule {
std::string rev;
private:
bool m_unconditional;
int m_referenceCount;
};

View File

@ -0,0 +1,63 @@
[
{
"enabled": 1,
"version_min": 300000,
"version_max": 0,
"title": "sec action",
"client": {
"ip": "200.249.12.31",
"port": 2313
},
"server": {
"ip": "200.249.12.31",
"port": 80
},
"request": {
"headers": {
"Host": "net.tutsplus.com",
"User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)",
"Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8",
"Accept-Language": "en-us,en;q=0.5",
"Accept-Encoding": "gzip,deflate",
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
"Keep-Alive": "300",
"Connection": "keep-alive",
"Cookie": "PHPSESSID=r2t5uvjq435r4q7ib3vtdjq120",
"Pragma": "no-cache",
"Cache-Control": "no-cache"
},
"uri": "\/test.pl?param1= test &param2=test2",
"protocol": "GET",
"http_version": 1.1,
"body": ""
},
"response": {
"headers": {
"Content-Type": "text\/xml; charset=utf-8\n\r",
"Content-Length": "length\n\r"
},
"body": [
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\r",
"<soap:Envelope xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\" xmlns:soap=\"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/\">\n\r",
" <soap:Body>\n\r",
" <EnlightenResponse xmlns=\"http:\/\/clearforest.com\/\">\n\r",
" <EnlightenResult>string<\/EnlightenResult>\n\r",
" <\/EnlightenResponse>\n\r",
" <\/soap:Body>\n\r",
"<\/soap:Envelope>\n\r"
]
},
"expected": {
"audit_log": "",
"debug_log": "Running unconditional rule.",
"error_log": ""
},
"rules": [
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"SecRule ARGS \"@contains test\" \"phase:2,id:1,t:trim\"",
"SecAction \"phase:2,nolog,pass\""
]
}
]