Adds support to SecMarker and skipAfter

This commit is contained in:
Felipe Zimmerle
2015-09-04 17:36:57 -03:00
parent b048794f4e
commit 5c3a4b608d
14 changed files with 288 additions and 4 deletions

View File

@@ -67,6 +67,7 @@ ACTIONS = \
actions/severity.cc \
actions/set_var.cc \
actions/status.cc \
actions/skip_after.cc \
actions/tag.cc \
actions/transformations/base64_decode.cc \
actions/transformations/base64_decode_ext.cc \

41
src/actions/skip_after.cc Normal file
View File

@@ -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 "actions/skip_after.h"
#include <iostream>
#include <string>
#include "actions/action.h"
#include "modsecurity/assay.h"
#include "src/utils.h"
namespace ModSecurity {
namespace actions {
SkipAfter::SkipAfter(std::string action)
: Action(action, RunTimeOnlyIfMatchKind),
m_marker(action) {
}
bool SkipAfter::evaluate(Rule *rule, Assay *assay) {
assay->debug(5, "Setting skipAfter for: " + m_marker);
assay->m_marker = m_marker;
return true;
}
} // namespace actions
} // namespace ModSecurity

44
src/actions/skip_after.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* 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 "actions/action.h"
#ifndef SRC_ACTIONS_SKIP_AFTER_H_
#define SRC_ACTIONS_SKIP_AFTER_H_
class Assay;
namespace ModSecurity {
class Assay;
namespace actions {
class SkipAfter : public Action {
public:
explicit SkipAfter(std::string action);
bool evaluate(Rule *rule, Assay *assay) override;
private:
std::string m_marker;
};
} // namespace actions
} // namespace ModSecurity
#endif // SRC_ACTIONS_SKIP_AFTER_H_

View File

@@ -103,6 +103,7 @@ Assay::Assay(ModSecurity *ms, Rules *rules)
m_requestBodyType(UnknownFormat),
m_requestHeadersNames(NULL),
m_responseHeadersNames(NULL),
m_marker(""),
start(cpu_seconds()),
m_ms(ms) {
id = std::to_string(this->timeStamp) + \

View File

@@ -39,6 +39,16 @@ Driver::~Driver() {
delete loc.back();
}
int Driver::addSecMarker(std::string marker) {
for (int i = 0; i < ModSecurity::Phases::NUMBER_OF_PHASES; i++) {
Rule *rule = new Rule(marker);
rule->phase = i;
rules[i].push_back(rule);
}
}
int Driver::addSecAction(Rule *rule) {
if (rule->phase >= ModSecurity::Phases::NUMBER_OF_PHASES) {
parserError << "Unknown phase: " << std::to_string(rule->phase);

View File

@@ -58,6 +58,7 @@ class Driver : public RulesProperties {
int addSecRule(Rule *rule);
int addSecAction(Rule *rule);
int addSecMarker(std::string marker);
int result;

View File

@@ -23,6 +23,7 @@ class Driver;
#include "actions/ctl_audit_log_parts.h"
#include "actions/set_var.h"
#include "actions/severity.h"
#include "actions/skip_after.h"
#include "actions/msg.h"
#include "actions/phase.h"
#include "actions/log_data.h"
@@ -192,6 +193,7 @@ using ModSecurity::Variables::Variable;
%token <std::string> CONFIG_DIR_SEC_ACTION
%token <std::string> CONFIG_DIR_SEC_DEFAULT_ACTION
%token <std::string> CONFIG_DIR_SEC_MARKER
%token <std::string> VARIABLE
%token <std::string> RUN_TIME_VAR_DUR
@@ -216,6 +218,7 @@ using ModSecurity::Variables::Variable;
%token <std::string> OPERATOR
%token <std::string> FREE_TEXT
%token <std::string> ACTION
%token <std::string> ACTION_SKIP_AFTER
%token <std::string> ACTION_AUDIT_LOG
%token <std::string> ACTION_SEVERITY
%token <std::string> ACTION_SETVAR
@@ -412,6 +415,10 @@ expression:
driver.defaultActions[definedPhase].push_back(a);
}
}
| CONFIG_DIR_SEC_MARKER
{
driver.addSecMarker($1);
}
| CONFIG_DIR_RULE_ENG SPACE CONFIG_VALUE_OFF
{
driver.secRuleEngine = ModSecurity::Rules::DisabledRuleEngine;
@@ -699,6 +706,10 @@ act:
$$ = setVar;
}
| ACTION_SKIP_AFTER
{
$$ = new ModSecurity::actions::SkipAfter($1);
}
| ACTION_AUDIT_LOG
{
$$ = new ModSecurity::actions::AuditLog($1);

View File

@@ -23,7 +23,8 @@ using ModSecurity::split;
%}
%option noyywrap nounput batch debug noinput
ACTION (?i:accuracy|allow|append|block|capture|chain|deny|deprecatevar|drop|exec|expirevar|id:[0-9]+|id:'[0-9]+'|initcol|log|maturity|multiMatch|noauditlog|nolog|pass|pause|prepend|proxy|redirect:[A-Z0-9_\|\&\:\/\/\.]+|sanitiseArg|sanitiseMatched|sanitiseMatchedBytes|sanitiseRequestHeader|sanitiseResponseHeader|setuid|setrsc|setsid|setenv|skip|skipAfter|status:[0-9]+|ver|xmlns)
ACTION (?i:accuracy|allow|append|block|capture|chain|deny|deprecatevar|drop|exec|expirevar|id:[0-9]+|id:'[0-9]+'|initcol|log|maturity|multiMatch|noauditlog|nolog|pass|pause|prepend|proxy|redirect:[A-Z0-9_\|\&\:\/\/\.]+|sanitiseArg|sanitiseMatched|sanitiseMatchedBytes|sanitiseRequestHeader|sanitiseResponseHeader|setuid|setrsc|setsid|setenv|skip|status:[0-9]+|ver|xmlns)
ACTION_SKIP_AFTER (?i:skipAfter)
ACTION_PHASE ((?i:phase:(?i:REQUEST|RESPONSE|LOGGING|[0-9]+))|(?i:phase:'(?i:REQUEST|RESPONSE|LOGGING|[0-9]+)'))
ACTION_AUDIT_LOG (?i:auditlog)
ACTION_SEVERITY (?i:severity)
@@ -40,6 +41,7 @@ LOG_DATA (?i:logdata)
CONFIG_DIR_SEC_DEFAULT_ACTION (?i:SecDefaultAction)
CONFIG_DIR_SEC_ACTION (?i:SecAction)
CONFIG_DIR_SEC_MARKER (?i:SecMarker)
CONFIG_DIR_PCRE_MATCH_LIMIT_RECURSION (?i:SecPcreMatchLimitRecursion)
CONFIG_DIR_PCRE_MATCH_LIMIT (?i:SecPcreMatchLimit)
@@ -246,6 +248,7 @@ CONFIG_DIR_UNICODE_MAP_FILE (?i:SecUnicodeMapFile)
{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()); }
{CONFIG_DIR_SEC_MARKER}[ ]{FREE_TEXT_NEW_LINE} { return yy::seclang_parser::make_CONFIG_DIR_SEC_MARKER(strchr(yytext, ' ') + 1, *driver.loc.back()); }
<EXPECTING_OPERATOR>{
["][^@]{FREE_TEXT}["] { BEGIN(INITIAL); return yy::seclang_parser::make_FREE_TEXT(yytext, *driver.loc.back()); }
@@ -255,6 +258,7 @@ CONFIG_DIR_UNICODE_MAP_FILE (?i:SecUnicodeMapFile)
{ACTION} { return yy::seclang_parser::make_ACTION(yytext, *driver.loc.back()); }
{ACTION_PHASE} { return yy::seclang_parser::make_ACTION(yytext, *driver.loc.back()); }
{ACTION_SKIP_AFTER}:{FREE_TEXT} { return yy::seclang_parser::make_ACTION_SKIP_AFTER(strchr(yytext, ':') + 1, *driver.loc.back()); }
{ACTION_AUDIT_LOG} { return yy::seclang_parser::make_ACTION_AUDIT_LOG(yytext, *driver.loc.back()); }
{ACTION_SEVERITY}:{ACTION_SEVERITY_VALUE} { return yy::seclang_parser::make_ACTION_SEVERITY(yytext + 9, *driver.loc.back()); }

View File

@@ -40,7 +40,9 @@ using Variables::Variable;
using actions::transformations::None;
Rule::~Rule() {
delete op;
if (op != NULL) {
delete op;
}
while (actions_conf.empty() == false) {
auto *a = actions_conf.back();
actions_conf.pop_back();
@@ -62,9 +64,22 @@ Rule::~Rule() {
delete a;
}
delete variables;
if (variables != NULL) {
delete variables;
}
}
Rule::Rule(std::string marker)
: chained(false),
chainedRule(NULL),
variables(NULL),
op(NULL),
rule_id(0),
phase(-1),
m_unconditional(false),
m_secmarker(true),
m_marker(marker),
m_referenceCount(0) { };
Rule::Rule(Operator *_op,
std::vector<Variable *> *_variables,
@@ -76,6 +91,8 @@ Rule::Rule(Operator *_op,
rule_id(0),
phase(-1),
m_unconditional(false),
m_secmarker(false),
m_marker(""),
m_referenceCount(0) {
for (Action *a : *actions) {
if (a->action_kind == Action::ConfigurationKind) {
@@ -170,6 +187,9 @@ bool Rule::evaluate(Assay *assay) {
bool ret = false;
std::vector<Variable *> *variables = this->variables;
if (m_secmarker == true) {
return true;
}
if (m_unconditional == true) {
return evaluateActions(assay);
}

View File

@@ -34,6 +34,7 @@ class Rule {
Rule(operators::Operator *_op,
std::vector<Variables::Variable *> *_variables,
std::vector<actions::Action *> *_actions);
explicit Rule(std::string marker);
~Rule();
bool evaluate(Assay *assay);
@@ -64,6 +65,8 @@ class Rule {
std::string rev;
std::string m_marker;
bool m_secmarker;
private:
bool m_unconditional;
int m_referenceCount;

View File

@@ -172,7 +172,19 @@ int Rules::evaluate(int phase, Assay *assay) {
for (int i = 0; i < rules.size(); i++) {
Rule *rule = rules[i];
rule->evaluate(assay);
if (assay->m_marker.empty()) {
rule->evaluate(assay);
} else {
debug(9, "Skipped rule id '" + std::to_string(rule->rule_id) + "' due to a SecMarker: " + assay->m_marker);
m_secmarker_skipped++;
debug(9, "Rule: " + rule->m_marker);
if (rule->m_secmarker && rule->m_marker == assay->m_marker) {
debug(4, "Out of a SecMarker after skip " \
+ std::to_string(m_secmarker_skipped) + " rules.");
assay->m_marker.clear();
m_secmarker_skipped = 0;
}
}
}
return 1;
}