Adds support to SecRemoteRules and Include directives

This commit includes a refactoring on important pieces of the parser
to allow it work in a stack fashion. Driver and Rules classes were
simplified and the RulesProperties class was created.
This commit is contained in:
Felipe Zimmerle 2015-07-24 19:15:25 -03:00
parent ec9a97324f
commit b8f7fb441d
14 changed files with 726 additions and 238 deletions

View File

@ -32,6 +32,7 @@ typedef struct Assay_t Assay;
#include "modsecurity/modsecurity.h" #include "modsecurity/modsecurity.h"
#include "modsecurity/assay.h" #include "modsecurity/assay.h"
#include "modsecurity/rules_properties.h"
#ifdef __cplusplus #ifdef __cplusplus
@ -43,30 +44,20 @@ class Driver;
} }
/** @ingroup ModSecurity_CPP_API */ /** @ingroup ModSecurity_CPP_API */
class Rules { class Rules : public RulesProperties {
public: public:
Rules() Rules()
: m_referenceCount(0), : RulesProperties(NULL) { }
requestBodyLimit(0),
responseBodyLimit(0),
m_custom_debug_log(NULL) { }
explicit Rules(DebugLog *custom_log) Rules(DebugLog *customLog)
: m_referenceCount(0), : RulesProperties(customLog) { }
m_custom_debug_log(custom_log) { }
~Rules(); ~Rules();
void incrementReferenceCount(void); void incrementReferenceCount(void);
void decrementReferenceCount(void); void decrementReferenceCount(void);
/** bool loadFromUri(const char *uri);
* FIXME:
*
* names should follow a patterner
*
*/
bool loadFromUri(char *uri);
bool loadRemote(char *key, char *uri); bool loadRemote(char *key, char *uri);
bool load(const char *rules); bool load(const char *rules);
bool load(const char *rules, const std::string &ref); bool load(const char *rules, const std::string &ref);
@ -79,81 +70,13 @@ class Rules {
int evaluate(int phase, Assay *assay); int evaluate(int phase, Assay *assay);
std::string getParserError(); std::string getParserError();
std::vector<Rule *> rules[7]; // Number of Phases.
/**
*
* The RuleEngine enumerator consists in mapping the different states
* of the rule engine.
*
*/
enum RuleEngine {
/**
* Rules won't be evaluated if Rule Engine is set to DisabledRuleEngine
*
*/
DisabledRuleEngine,
/**
* Rules will be evaluated and disturb actions will take place if needed.
*
*/
EnabledRuleEngine,
/**
* Rules will be evaluated but it won't generate any disruptive action.
*
*/
DetectionOnlyRuleEngine
};
enum BodyLimitAction {
/**
* Process partial
*
*/
ProcessPartialBodyLimitAction,
/**
* Process partial
*
*/
RejectBodyLimitAction
};
static const char *ruleEngineStateString(RuleEngine i) {
switch (i) {
case DisabledRuleEngine:
return "Disabled";
case EnabledRuleEngine:
return "Enabled";
case DetectionOnlyRuleEngine:
return "DetectionOnly";
}
return NULL;
}
RuleEngine secRuleEngine;
int sec_audit_type;
bool sec_audit_engine;
bool sec_request_body_access;
bool sec_response_body_access;
std::string audit_log_path;
std::string audit_log_parts;
std::string debug_log_path;
int debug_level;
DebugLog *debug_log;
void debug(int level, std::string message); void debug(int level, std::string message);
std::list<std::string> components;
int requestBodyLimit;
int responseBodyLimit;
int requestBodyLimitAction;
int responseBodyLimitAction;
std::ostringstream parserError; std::ostringstream parserError;
AuditLog *audit_log; DebugLog *debugLog;
private: private:
int m_referenceCount; int m_referenceCount;
DebugLog *m_custom_debug_log;
}; };
#endif #endif

View File

@ -0,0 +1,187 @@
/*
* 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.
*
*/
#ifdef __cplusplus
#include <ctime>
#include <iostream>
#include <string>
#include <vector>
#include <list>
#endif
#ifndef HEADERS_MODSECURITY_RULES_PROPERTIES_H_
#define HEADERS_MODSECURITY_RULES_PROPERTIES_H_
#include "modsecurity/modsecurity.h"
#include "modsecurity/assay.h"
#include "modsecurity/assay.h"
#ifdef __cplusplus
namespace ModSecurity {
class Rule;
class AuditLog;
namespace Parser {
class Driver;
}
/** @ingroup ModSecurity_CPP_API */
class RulesProperties {
public:
RulesProperties()
: audit_log(NULL),
customDebugLog(NULL),
remoteRulesActionOnFailed(AbortOnFailedRemoteRulesAction),
requestBodyLimit(0),
requestBodyLimitAction(ProcessPartialBodyLimitAction),
responseBodyLimit(0),
responseBodyLimitAction(ProcessPartialBodyLimitAction),
secRuleEngine(DetectionOnlyRuleEngine) { }
explicit RulesProperties(DebugLog *customDebugLog)
: audit_log(NULL),
customDebugLog(customDebugLog),
remoteRulesActionOnFailed(AbortOnFailedRemoteRulesAction),
requestBodyLimit(0),
requestBodyLimitAction(ProcessPartialBodyLimitAction),
responseBodyLimit(0),
responseBodyLimitAction(ProcessPartialBodyLimitAction),
secRuleEngine(DetectionOnlyRuleEngine) { }
~RulesProperties() { };
std::vector<Rule *> rules[7]; // ModSecurity::Phases::NUMBER_OF_PHASES
/**
*
* The RuleEngine enumerator consists in mapping the different states
* of the rule engine.
*
*/
enum RuleEngine {
/**
*
* Rules won't be evaluated if Rule Engine is set to DisabledRuleEngine
*
*/
DisabledRuleEngine,
/**
*
* Rules will be evaluated and disturb actions will take place if needed.
*
*/
EnabledRuleEngine,
/**
* Rules will be evaluated but it won't generate any disruptive action.
*
*/
DetectionOnlyRuleEngine
};
/**
*
* Defines what actions should be taken in case the body (response or
* request) is bigger than the expected size.
*
*/
enum BodyLimitAction {
/**
*
* Process partial
*
*/
ProcessPartialBodyLimitAction,
/**
*
* Reject the request
*
*/
RejectBodyLimitAction
};
/**
*
* Defines what actions should be taken in case the remote rules failed to
* be downloaded (independent of the circumstances)
*
*
*/
enum OnFailedRemoteRulesAction {
/**
*
* Abort
*
*/
AbortOnFailedRemoteRulesAction,
/**
*
* Warn on logging
*
*/
WarnOnFailedRemoteRulesAction
};
static const char *ruleEngineStateString(RuleEngine i) {
switch (i) {
case DisabledRuleEngine:
return "Disabled";
case EnabledRuleEngine:
return "Enabled";
case DetectionOnlyRuleEngine:
return "DetectionOnly";
}
return NULL;
}
RuleEngine secRuleEngine;
double requestBodyLimit;
double responseBodyLimit;
BodyLimitAction requestBodyLimitAction;
BodyLimitAction responseBodyLimitAction;
DebugLog *customDebugLog;
int sec_audit_type;
bool sec_audit_engine;
bool sec_request_body_access;
bool sec_response_body_access;
std::string audit_log_path;
std::string audit_log_parts;
std::string debug_log_path;
int debug_level;
std::list<std::string> components;
std::ostringstream parserError;
AuditLog *audit_log;
OnFailedRemoteRulesAction remoteRulesActionOnFailed;
};
#endif
#ifdef __cplusplus
} // namespace ModSecurity
#endif
#endif // HEADERS_MODSECURITY_RULES_PROPERTIES_H_

View File

@ -22,11 +22,12 @@ MAINTAINERCLEANFILES = \
pkginclude_HEADERS = \ pkginclude_HEADERS = \
../headers/modsecurity/modsecurity.h \ ../headers/modsecurity/assay.h \
../headers/modsecurity/assay.h \ ../headers/modsecurity/debug_log.h \
../headers/modsecurity/rules.h \ ../headers/modsecurity/intervention.h \
../headers/modsecurity/debug_log.h \ ../headers/modsecurity/modsecurity.h \
../headers/modsecurity/intervention.h ../headers/modsecurity/rules.h \
../headers/modsecurity/rules_properties.h
VARIABLES = \ VARIABLES = \

View File

@ -517,7 +517,9 @@ int Assay::processRequestBody() {
if (m_requestBodyType == WWWFormUrlEncoded) { if (m_requestBodyType == WWWFormUrlEncoded) {
std::string content = uri_decode(m_requestBody.str()); std::string content = uri_decode(m_requestBody.str());
content.erase(content.length()-1, 1); if (content.empty() == false) {
content.pop_back();
}
/** /**
* FIXME: * FIXME:
@ -577,7 +579,7 @@ int Assay::processRequestBody() {
store_variable("FULL_REQUEST", fullRequest); store_variable("FULL_REQUEST", fullRequest);
store_variable("FULL_REQUEST_LENGTH", std::to_string(fullRequest.size())); store_variable("FULL_REQUEST_LENGTH", std::to_string(fullRequest.size()));
if (m_requestBody.tellp() <= 0) { if (m_requestBody.tellp() > 0) {
store_variable("REQUEST_BODY", m_requestBody.str()); store_variable("REQUEST_BODY", m_requestBody.str());
store_variable("REQUEST_BODY_LENGTH", store_variable("REQUEST_BODY_LENGTH",
std::to_string(m_requestBody.str().size())); std::to_string(m_requestBody.str().size()));

View File

@ -64,14 +64,18 @@ int Driver::addSecRule(Rule *rule) {
} }
} }
this->rules[rule->phase].push_back(rule); rules[rule->phase].push_back(rule);
return true; return true;
} }
int Driver::parse(const std::string &f, const std::string &ref) { int Driver::parse(const std::string &f, const std::string &ref) {
this->ref = ref; if (ref.empty()) {
this->ref = "<<reference missing or not informed>>";
} else {
this->ref = ref;
}
buffer = f; buffer = f;
scan_begin(); scan_begin();
yy::seclang_parser parser(*this); yy::seclang_parser parser(*this);
@ -81,43 +85,48 @@ int Driver::parse(const std::string &f, const std::string &ref) {
if (audit_log->init() == false) { if (audit_log->init() == false) {
return false; return false;
} }
scan_end(); scan_end();
return res == 0; return res == 0;
} }
int Driver::parseFile(const std::string &f) { int Driver::parseFile(const std::string &f) {
this->ref = f; std::ifstream t(f);
file = f; std::string str;
scan_begin();
yy::seclang_parser parser(*this);
parser.set_debug_level(trace_parsing);
int res = parser.parse();
if (audit_log->init() == false) { if (t.is_open() == false) {
parserError << "Failed to open the file: " << f << std::endl;
return false; return false;
} }
scan_end(); t.seekg(0, std::ios::end);
return res == 0; str.reserve(t.tellg());
t.seekg(0, std::ios::beg);
str.assign((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
return parse(str, f);
}
void Driver::error(const yy::location& l, const std::string& m) {
error(l, m, "");
} }
void Driver::error(const yy::location& l, const std::string& m, void Driver::error(const yy::location& l, const std::string& m,
const std::string& c) { const std::string& c) {
if (parserError.tellp() == 0) { if (parserError.tellp() == 0) {
parserError << "Parser error, "; parserError << "Configuration error, ";
parserError << "File: " << ref << ". "; parserError << "File: " << ref << ". ";
parserError << "Line: " << l.end.line << ". "; parserError << "Line: " << l.end.line << ". ";
parserError << "Column: " << l.end.column << ". "; parserError << "Column: " << l.end.column << ". ";
} }
parserError << c; if (c.empty() == false) {
} parserError << c;
}
void Driver::parser_error(const yy::location& l, const std::string& m) {
parserError << ". " << m << "." << std::endl;
} }

View File

@ -27,6 +27,7 @@
#include "modsecurity/modsecurity.h" #include "modsecurity/modsecurity.h"
#include "src/rule.h" #include "src/rule.h"
#include "modsecurity/rules.h" #include "modsecurity/rules.h"
#include "modsecurity/rules_properties.h"
#include "src/audit_log.h" #include "src/audit_log.h"
#include "parser/seclang-parser.hh" #include "parser/seclang-parser.hh"
@ -50,11 +51,7 @@ typedef struct Driver_t Driver;
#endif #endif
class Driver : public Rules { class Driver : public RulesProperties {
/**
* @todo Place driver and parser under the correct namespace.
*
*/
public: public:
Driver(); Driver();
virtual ~Driver(); virtual ~Driver();
@ -63,30 +60,23 @@ class Driver : public Rules {
int result; int result;
// Handling the scanner. bool scan_begin();
void scan_begin();
void scan_end(); void scan_end();
bool trace_scanning; bool trace_scanning;
// Run the parser on file F.
// Return 0 on success.
int parseFile(const std::string& f); int parseFile(const std::string& f);
int parse(const std::string& f, const std::string &ref); int parse(const std::string& f, const std::string &ref);
// The name of the file being parsed.
// Used later to pass the file name to the location tracker.
std::string file; std::string file;
// Whether parser traces should be generated.
bool trace_parsing; bool trace_parsing;
// Error handling.
void error(const yy::location& l, const std::string& m); void error(const yy::location& l, const std::string& m);
void parser_error(const yy::location& l, const std::string& m);
void error(const yy::location& l, const std::string& m, void error(const yy::location& l, const std::string& m,
const std::string& c); const std::string& c);
yy::location loc;
std::string ref; std::string ref;
std::string buffer; std::string buffer;
}; };

View File

@ -4,6 +4,7 @@
%define parser_class_name {seclang_parser} %define parser_class_name {seclang_parser}
%define api.token.constructor %define api.token.constructor
%define api.value.type variant %define api.value.type variant
//%define api.namespace {ModSecurity::yy}
%define parse.assert %define parse.assert
%code requires %code requires
{ {
@ -103,6 +104,8 @@ using ModSecurity::Variables::Variable;
%token <std::string> CONFIG_VALUE_RELEVANT_ONLY %token <std::string> CONFIG_VALUE_RELEVANT_ONLY
%token <std::string> CONFIG_VALUE_PROCESS_PARTIAL %token <std::string> CONFIG_VALUE_PROCESS_PARTIAL
%token <std::string> CONFIG_VALUE_REJECT %token <std::string> CONFIG_VALUE_REJECT
%token <std::string> CONFIG_VALUE_ABORT
%token <std::string> CONFIG_VALUE_WARN
%token <std::string> CONFIG_DIR_AUDIT_DIR %token <std::string> CONFIG_DIR_AUDIT_DIR
%token <std::string> CONFIG_DIR_AUDIT_DIR_MOD %token <std::string> CONFIG_DIR_AUDIT_DIR_MOD
@ -135,6 +138,10 @@ using ModSecurity::Variables::Variable;
%token <std::string> RUN_TIME_VAR_TIME_WDAY %token <std::string> RUN_TIME_VAR_TIME_WDAY
%token <std::string> RUN_TIME_VAR_TIME_YEAR %token <std::string> RUN_TIME_VAR_TIME_YEAR
%token <std::string> CONFIG_INCLUDE
%token <std::string> CONFIG_SEC_REMOTE_RULES
%token <std::string> CONFIG_SEC_REMOTE_RULES_FAIL_ACTION
%token <std::string> CONFIG_DIR_GEO_DB %token <std::string> CONFIG_DIR_GEO_DB
%token <std::string> OPERATOR %token <std::string> OPERATOR
@ -316,6 +323,14 @@ expression:
{ {
driver.responseBodyLimitAction = ModSecurity::Rules::BodyLimitAction::RejectBodyLimitAction; driver.responseBodyLimitAction = ModSecurity::Rules::BodyLimitAction::RejectBodyLimitAction;
} }
| CONFIG_SEC_REMOTE_RULES_FAIL_ACTION CONFIG_VALUE_ABORT
{
driver.remoteRulesActionOnFailed = Rules::OnFailedRemoteRulesAction::AbortOnFailedRemoteRulesAction;
}
| CONFIG_SEC_REMOTE_RULES_FAIL_ACTION CONFIG_VALUE_WARN
{
driver.remoteRulesActionOnFailed = Rules::OnFailedRemoteRulesAction::WarnOnFailedRemoteRulesAction;
}
variables: variables:
variables PIPE VARIABLE variables PIPE VARIABLE
@ -572,5 +587,5 @@ void
yy::seclang_parser::error (const location_type& l, yy::seclang_parser::error (const location_type& l,
const std::string& m) const std::string& m)
{ {
driver.parser_error (l, m); driver.error (l, m);
} }

View File

@ -1,12 +1,16 @@
%{ /* -*- C++ -*- */ %{ /* -*- C++ -*- */
# include <cerrno> #include <cerrno>
# include <climits> #include <climits>
# include <cstdlib> #include <cstdlib>
# include <string> #include <string>
# include "parser/driver.h" #include "parser/driver.h"
# include "seclang-parser.hh" #include "seclang-parser.hh"
#include "utils/https_client.h"
#include "utils.h"
using ModSecurity::Parser::Driver; using ModSecurity::Parser::Driver;
using ModSecurity::Utils::HttpsClient;
using ModSecurity::split;
// Work around an incompatibility in flex (at least versions // Work around an incompatibility in flex (at least versions
// 2.5.31 through 2.5.33): it generates code that does // 2.5.31 through 2.5.33): it generates code that does
@ -16,9 +20,9 @@ using ModSecurity::Parser::Driver;
# define yywrap() 1 # define yywrap() 1
// The location of the current token. // The location of the current token.
static yy::location loc;
%} %}
%option noyywrap nounput batch debug noinput %option noyywrap nounput batch debug noinput
ACTION (?i:accuracy|allow|append|auditlog|block|capture|chain|ctl|deny|deprecatevar|drop|exec|expirevar|id:[0-9]+|id:'[0-9]+'|initcol|log|logdata|maturity|msg|multiMatch|noauditlog|nolog|pass|pause|phase:[0-9]+|prepend|proxy|redirect:[A-Z0-9_\|\&\:\/\/\.]+|rev|sanitiseArg|sanitiseMatched|sanitiseMatchedBytes|sanitiseRequestHeader|sanitiseResponseHeader|setuid|setrsc|setsid|setenv|setvar|skip|skipAfter|status:[0-9]+|tag|ver|xmlns) ACTION (?i:accuracy|allow|append|auditlog|block|capture|chain|ctl|deny|deprecatevar|drop|exec|expirevar|id:[0-9]+|id:'[0-9]+'|initcol|log|logdata|maturity|msg|multiMatch|noauditlog|nolog|pass|pause|phase:[0-9]+|prepend|proxy|redirect:[A-Z0-9_\|\&\:\/\/\.]+|rev|sanitiseArg|sanitiseMatched|sanitiseMatchedBytes|sanitiseRequestHeader|sanitiseResponseHeader|setuid|setrsc|setsid|setenv|setvar|skip|skipAfter|status:[0-9]+|tag|ver|xmlns)
ACTION_SEVERITY (?i:severity:[0-9]+|severity:'[0-9]+'|severity:(EMERGENCY|ALERT|CRITICAL|ERROR|WARNING|NOTICE|INFO|DEBUG)|severity:'(EMERGENCY|ALERT|CRITICAL|ERROR|WARNING|NOTICE|INFO|DEBUG)') ACTION_SEVERITY (?i:severity:[0-9]+|severity:'[0-9]+'|severity:(EMERGENCY|ALERT|CRITICAL|ERROR|WARNING|NOTICE|INFO|DEBUG)|severity:'(EMERGENCY|ALERT|CRITICAL|ERROR|WARNING|NOTICE|INFO|DEBUG)')
DIRECTIVE SecRule DIRECTIVE SecRule
@ -53,7 +57,11 @@ CONFIG_DIR_DEBUG_LVL SecDebugLogLevel
CONFIG_COMPONENT_SIG (?i:SecComponentSignature) CONFIG_COMPONENT_SIG (?i:SecComponentSignature)
CONFIG_INCLUDE Include CONFIG_INCLUDE (?i:Include)
CONFIG_SEC_REMOTE_RULES (?i:SecRemoteRules)
CONFIG_SEC_REMOTE_RULES_FAIL_ACTION (?i:SecRemoteRulesFailAction)
DICT_ELEMENT [A-Za-z_]+ DICT_ELEMENT [A-Za-z_]+
@ -92,8 +100,10 @@ CONFIG_VALUE_RELEVANT_ONLY RelevantOnly
CONFIG_VALUE_PROCESS_PARTIAL (?i:ProcessPartial) CONFIG_VALUE_PROCESS_PARTIAL (?i:ProcessPartial)
CONFIG_VALUE_REJECT (?i:Reject) CONFIG_VALUE_REJECT (?i:Reject)
CONFIG_VALUE_ABORT (?i:Abort)
CONFIG_VALUE_WARN (?i:Warn)
CONFIG_VALUE_PATH [A-Za-z_/\.]+ CONFIG_VALUE_PATH [0-9A-Za-z_/\.\-]+
AUDIT_PARTS [ABCDEFHJKZ]+ AUDIT_PARTS [ABCDEFHJKZ]+
CONFIG_VALUE_NUMBER [0-9]+ CONFIG_VALUE_NUMBER [0-9]+
@ -102,112 +112,155 @@ FREE_TEXT_NEW_LINE [^\"|\n]+
%{ %{
// Code run each time a pattern is matched. // Code run each time a pattern is matched.
# define YY_USER_ACTION loc.columns (yyleng); # define YY_USER_ACTION driver.loc.columns (yyleng);
%} %}
%% %%
%{ %{
// Code run each time yylex is called. // Code run each time yylex is called.
loc.step(); driver.loc.step();
%} %}
{DIRECTIVE} { return yy::seclang_parser::make_DIRECTIVE(yytext, loc); } {DIRECTIVE} { return yy::seclang_parser::make_DIRECTIVE(yytext, driver.loc); }
{TRANSFORMATION} { return yy::seclang_parser::make_TRANSFORMATION(yytext, loc); } {TRANSFORMATION} { return yy::seclang_parser::make_TRANSFORMATION(yytext, driver.loc); }
{CONFIG_DIR_RULE_ENG} { return yy::seclang_parser::make_CONFIG_DIR_RULE_ENG(yytext, loc); } {CONFIG_DIR_RULE_ENG} { return yy::seclang_parser::make_CONFIG_DIR_RULE_ENG(yytext, driver.loc); }
{CONFIG_DIR_RES_BODY} { return yy::seclang_parser::make_CONFIG_DIR_RES_BODY(yytext, loc); } {CONFIG_DIR_RES_BODY} { return yy::seclang_parser::make_CONFIG_DIR_RES_BODY(yytext, driver.loc); }
{CONFIG_DIR_REQ_BODY} { return yy::seclang_parser::make_CONFIG_DIR_REQ_BODY(yytext, loc); } {CONFIG_DIR_REQ_BODY} { return yy::seclang_parser::make_CONFIG_DIR_REQ_BODY(yytext, driver.loc); }
%{ /* Audit log entries */ %} %{ /* Audit log entries */ %}
{CONFIG_DIR_AUDIT_DIR}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_DIR(strchr(yytext, ' ') + 1, loc); } {CONFIG_DIR_AUDIT_DIR}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_DIR(strchr(yytext, ' ') + 1, driver.loc); }
{CONFIG_DIR_AUDIT_DIR_MOD}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_DIR_MOD(strchr(yytext, ' ') + 1, loc); } {CONFIG_DIR_AUDIT_DIR_MOD}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_DIR_MOD(strchr(yytext, ' ') + 1, driver.loc); }
{CONFIG_DIR_AUDIT_ENG} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_ENG(yytext, loc); } {CONFIG_DIR_AUDIT_ENG} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_ENG(yytext, driver.loc); }
{CONFIG_DIR_AUDIT_FLE_MOD}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_FLE_MOD(strchr(yytext, ' ') + 1, loc); } {CONFIG_DIR_AUDIT_FLE_MOD}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_FLE_MOD(strchr(yytext, ' ') + 1, driver.loc); }
{CONFIG_DIR_AUDIT_LOG2}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_LOG2(strchr(yytext, ' ') + 1, loc); } {CONFIG_DIR_AUDIT_LOG2}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_LOG2(strchr(yytext, ' ') + 1, driver.loc); }
{CONFIG_DIR_AUDIT_LOG}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_LOG(strchr(yytext, ' ') + 1, loc); } {CONFIG_DIR_AUDIT_LOG}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_LOG(strchr(yytext, ' ') + 1, driver.loc); }
{CONFIG_DIR_AUDIT_LOG_P}[ ]{AUDIT_PARTS} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_LOG_P(strchr(yytext, ' ') + 1, loc); } {CONFIG_DIR_AUDIT_LOG_P}[ ]{AUDIT_PARTS} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_LOG_P(strchr(yytext, ' ') + 1, driver.loc); }
{CONFIG_DIR_AUDIT_STS}[ ]["]{FREE_TEXT}["] { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_STS(strchr(yytext, ' ') + 1, loc); } {CONFIG_DIR_AUDIT_STS}[ ]["]{FREE_TEXT}["] { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_STS(strchr(yytext, ' ') + 1, driver.loc); }
{CONFIG_DIR_AUDIT_TPE} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_TPE(yytext, loc); } {CONFIG_DIR_AUDIT_TPE} { return yy::seclang_parser::make_CONFIG_DIR_AUDIT_TPE(yytext, driver.loc); }
%{ /* Debug log entries */ %} %{ /* Debug log entries */ %}
{CONFIG_DIR_DEBUG_LOG}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_DEBUG_LOG(strchr(yytext, ' ') + 1, loc); } {CONFIG_DIR_DEBUG_LOG}[ ]{CONFIG_VALUE_PATH} { return yy::seclang_parser::make_CONFIG_DIR_DEBUG_LOG(strchr(yytext, ' ') + 1, driver.loc); }
{CONFIG_DIR_DEBUG_LVL}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_DEBUG_LVL(strchr(yytext, ' ') + 1, loc); } {CONFIG_DIR_DEBUG_LVL}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_DEBUG_LVL(strchr(yytext, ' ') + 1, driver.loc); }
%{ /* Variables */ %} %{ /* Variables */ %}
{VARIABLE}:?{DICT_ELEMENT}? { return yy::seclang_parser::make_VARIABLE(yytext, loc); } {VARIABLE}:?{DICT_ELEMENT}? { return yy::seclang_parser::make_VARIABLE(yytext, driver.loc); }
{RUN_TIME_VAR_DUR} { return yy::seclang_parser::make_RUN_TIME_VAR_DUR(yytext, loc); } {RUN_TIME_VAR_DUR} { return yy::seclang_parser::make_RUN_TIME_VAR_DUR(yytext, driver.loc); }
{RUN_TIME_VAR_ENV}:?{DICT_ELEMENT}? { return yy::seclang_parser::make_RUN_TIME_VAR_ENV(yytext, loc); } {RUN_TIME_VAR_ENV}:?{DICT_ELEMENT}? { return yy::seclang_parser::make_RUN_TIME_VAR_ENV(yytext, driver.loc); }
{RUN_TIME_VAR_BLD} { return yy::seclang_parser::make_RUN_TIME_VAR_BLD(yytext, loc); } {RUN_TIME_VAR_BLD} { return yy::seclang_parser::make_RUN_TIME_VAR_BLD(yytext, driver.loc); }
{RUN_TIME_VAR_HSV} { return yy::seclang_parser::make_RUN_TIME_VAR_HSV(yytext, loc); } {RUN_TIME_VAR_HSV} { return yy::seclang_parser::make_RUN_TIME_VAR_HSV(yytext, driver.loc); }
%{ /* Variables: TIME */ %} %{ /* Variables: TIME */ %}
{RUN_TIME_VAR_TIME} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME(yytext, loc); } {RUN_TIME_VAR_TIME} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME(yytext, driver.loc); }
{RUN_TIME_VAR_TIME_DAY} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_DAY(yytext, loc); } {RUN_TIME_VAR_TIME_DAY} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_DAY(yytext, driver.loc); }
{RUN_TIME_VAR_TIME_EPOCH} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_EPOCH(yytext, loc); } {RUN_TIME_VAR_TIME_EPOCH} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_EPOCH(yytext, driver.loc); }
{RUN_TIME_VAR_TIME_HOUR} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_HOUR(yytext, loc); } {RUN_TIME_VAR_TIME_HOUR} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_HOUR(yytext, driver.loc); }
{RUN_TIME_VAR_TIME_MIN} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_MIN(yytext, loc); } {RUN_TIME_VAR_TIME_MIN} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_MIN(yytext, driver.loc); }
{RUN_TIME_VAR_TIME_MON} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_MON(yytext, loc); } {RUN_TIME_VAR_TIME_MON} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_MON(yytext, driver.loc); }
{RUN_TIME_VAR_TIME_SEC} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_SEC(yytext, loc); } {RUN_TIME_VAR_TIME_SEC} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_SEC(yytext, driver.loc); }
{RUN_TIME_VAR_TIME_WDAY} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_WDAY(yytext, loc); } {RUN_TIME_VAR_TIME_WDAY} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_WDAY(yytext, driver.loc); }
{RUN_TIME_VAR_TIME_YEAR} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_YEAR(yytext, loc); } {RUN_TIME_VAR_TIME_YEAR} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_YEAR(yytext, driver.loc); }
%{ /* Geo DB loopkup */ %} %{ /* Geo DB loopkup */ %}
{CONFIG_DIR_GEO_DB}[ ]{FREE_TEXT_NEW_LINE} { return yy::seclang_parser::make_CONFIG_DIR_GEO_DB(strchr(yytext, ' ') + 1, loc); } {CONFIG_DIR_GEO_DB}[ ]{FREE_TEXT_NEW_LINE} { return yy::seclang_parser::make_CONFIG_DIR_GEO_DB(strchr(yytext, ' ') + 1, driver.loc); }
%{ /* Request body limit */ %} %{ /* Request body limit */ %}
{CONFIG_DIR_REQ_BODY_LIMIT}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_REQ_BODY_LIMIT(strchr(yytext, ' ') + 1, loc); } {CONFIG_DIR_REQ_BODY_LIMIT}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_REQ_BODY_LIMIT(strchr(yytext, ' ') + 1, driver.loc); }
{CONFIG_DIR_REQ_BODY_LIMIT_ACTION} { return yy::seclang_parser::make_CONFIG_DIR_REQ_BODY_LIMIT_ACTION(yytext, loc); } {CONFIG_DIR_REQ_BODY_LIMIT_ACTION} { return yy::seclang_parser::make_CONFIG_DIR_REQ_BODY_LIMIT_ACTION(yytext, driver.loc); }
%{ /* Reponse body limit */ %} %{ /* Reponse body limit */ %}
{CONFIG_DIR_RES_BODY_LIMIT}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_RES_BODY_LIMIT(strchr(yytext, ' ') + 1, loc); } {CONFIG_DIR_RES_BODY_LIMIT}[ ]{CONFIG_VALUE_NUMBER} { return yy::seclang_parser::make_CONFIG_DIR_RES_BODY_LIMIT(strchr(yytext, ' ') + 1, driver.loc); }
{CONFIG_DIR_RES_BODY_LIMIT_ACTION} { return yy::seclang_parser::make_CONFIG_DIR_RES_BODY_LIMIT_ACTION(yytext, loc); } {CONFIG_DIR_RES_BODY_LIMIT_ACTION} { return yy::seclang_parser::make_CONFIG_DIR_RES_BODY_LIMIT_ACTION(yytext, driver.loc); }
{CONFIG_COMPONENT_SIG}[ ]["]{FREE_TEXT}["] { return yy::seclang_parser::make_CONFIG_COMPONENT_SIG(strchr(yytext, ' ') + 2, loc); } {CONFIG_COMPONENT_SIG}[ ]["]{FREE_TEXT}["] { return yy::seclang_parser::make_CONFIG_COMPONENT_SIG(strchr(yytext, ' ') + 2, driver.loc); }
{CONFIG_VALUE_ON} { return yy::seclang_parser::make_CONFIG_VALUE_ON(yytext, loc); } {CONFIG_VALUE_WARN} { return yy::seclang_parser::make_CONFIG_VALUE_WARN(yytext, driver.loc); }
{CONFIG_VALUE_OFF} { return yy::seclang_parser::make_CONFIG_VALUE_OFF(yytext, loc); } {CONFIG_VALUE_ABORT} { return yy::seclang_parser::make_CONFIG_VALUE_ABORT(yytext, driver.loc); }
{CONFIG_VALUE_SERIAL} { return yy::seclang_parser::make_CONFIG_VALUE_SERIAL(yytext, loc); } {CONFIG_VALUE_ON} { return yy::seclang_parser::make_CONFIG_VALUE_ON(yytext, driver.loc); }
{CONFIG_VALUE_PARALLEL} { return yy::seclang_parser::make_CONFIG_VALUE_PARALLEL(yytext, loc); } {CONFIG_VALUE_OFF} { return yy::seclang_parser::make_CONFIG_VALUE_OFF(yytext, driver.loc); }
{CONFIG_VALUE_DETC} { return yy::seclang_parser::make_CONFIG_VALUE_DETC(yytext, loc); } {CONFIG_VALUE_SERIAL} { return yy::seclang_parser::make_CONFIG_VALUE_SERIAL(yytext, driver.loc); }
{CONFIG_VALUE_RELEVANT_ONLY} { return yy::seclang_parser::make_CONFIG_VALUE_RELEVANT_ONLY(yytext, loc); } {CONFIG_VALUE_PARALLEL} { return yy::seclang_parser::make_CONFIG_VALUE_PARALLEL(yytext, driver.loc); }
{CONFIG_VALUE_PROCESS_PARTIAL} { return yy::seclang_parser::make_CONFIG_VALUE_PROCESS_PARTIAL(yytext, loc); } {CONFIG_VALUE_DETC} { return yy::seclang_parser::make_CONFIG_VALUE_DETC(yytext, driver.loc); }
{CONFIG_VALUE_REJECT} { return yy::seclang_parser::make_CONFIG_VALUE_REJECT(yytext, loc); } {CONFIG_VALUE_RELEVANT_ONLY} { return yy::seclang_parser::make_CONFIG_VALUE_RELEVANT_ONLY(yytext, driver.loc); }
{CONFIG_VALUE_PROCESS_PARTIAL} { return yy::seclang_parser::make_CONFIG_VALUE_PROCESS_PARTIAL(yytext, driver.loc); }
{CONFIG_VALUE_REJECT} { return yy::seclang_parser::make_CONFIG_VALUE_REJECT(yytext, driver.loc); }
["]{OPERATOR}[ ]{FREE_TEXT}["] { return yy::seclang_parser::make_OPERATOR(yytext, driver.loc); }
["]{OPERATORNOARG}["] { return yy::seclang_parser::make_OPERATOR(yytext, driver.loc); }
{ACTION} { return yy::seclang_parser::make_ACTION(yytext, driver.loc); }
{ACTION_SEVERITY} { return yy::seclang_parser::make_ACTION_SEVERITY(yytext, driver.loc); }
["] { return yy::seclang_parser::make_QUOTATION_MARK(driver.loc); }
[,] { return yy::seclang_parser::make_COMMA(driver.loc); }
[|] { return yy::seclang_parser::make_PIPE(driver.loc); }
{VARIABLENOCOLON} { return yy::seclang_parser::make_VARIABLE(yytext, driver.loc); }
[ \t]+ { return yy::seclang_parser::make_SPACE(driver.loc); }
[\n]+ { driver.loc.lines(yyleng); driver.loc.step(); }
. { driver.error (driver.loc, "invalid character", yytext); }
<<EOF>> {
if (yyin) {
fclose(yyin);
}
yypop_buffer_state();
if (!YY_CURRENT_BUFFER)
{
return yy::seclang_parser::make_END(driver.loc);
}
}
%{ /* Include external configurations */ %}
{CONFIG_INCLUDE}[ ]{CONFIG_VALUE_PATH} {
const char *file = strchr(yytext, ' ') + 1;
yyin = fopen(file, "r" );
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
}
{CONFIG_SEC_REMOTE_RULES}[ ][^ ]+[ ][^\n\r ]+ {
HttpsClient c;
std::string key;
std::string url;
std::vector<std::string> conf = split(yytext, ' ');
key = conf[1];
url = conf[2];
YY_BUFFER_STATE temp = YY_CURRENT_BUFFER;
yypush_buffer_state(temp);
bool ret = c.download(url);
if (ret == false) {
/**
* TODO: Implement the fail action.
*
*/
if (driver.remoteRulesActionOnFailed == Rules::OnFailedRemoteRulesAction::WarnOnFailedRemoteRulesAction) {
}
if (driver.remoteRulesActionOnFailed == Rules::OnFailedRemoteRulesAction::AbortOnFailedRemoteRulesAction) {
}
}
yy_scan_string(c.content.c_str());
}
{CONFIG_SEC_REMOTE_RULES_FAIL_ACTION} { return yy::seclang_parser::make_CONFIG_SEC_REMOTE_RULES_FAIL_ACTION(yytext, driver.loc); }
["]{OPERATOR}[ ]{FREE_TEXT}["] { return yy::seclang_parser::make_OPERATOR(yytext, loc); }
["]{OPERATORNOARG}["] { return yy::seclang_parser::make_OPERATOR(yytext, loc); }
{ACTION} { return yy::seclang_parser::make_ACTION(yytext, loc); }
{ACTION_SEVERITY} { return yy::seclang_parser::make_ACTION_SEVERITY(yytext, loc); }
["] { return yy::seclang_parser::make_QUOTATION_MARK(loc); }
[,] { return yy::seclang_parser::make_COMMA(loc); }
[|] { return yy::seclang_parser::make_PIPE(loc); }
{VARIABLENOCOLON} { return yy::seclang_parser::make_VARIABLE(yytext, loc); }
[ \t]+ { return yy::seclang_parser::make_SPACE(loc); }
[\n]+ { loc.lines(yyleng); loc.step(); }
. { driver.error (loc, "invalid character", yytext); }
<<EOF>> { return yy::seclang_parser::make_END(loc); }
%% %%
namespace ModSecurity { namespace ModSecurity {
void Driver::scan_begin () { bool Driver::scan_begin () {
yy_flex_debug = trace_scanning; yy_flex_debug = trace_scanning;
if (buffer.empty() == false) { if (buffer.empty() == false) {
yy_scan_string(buffer.c_str()); yy_scan_string(buffer.c_str());
} else if (file.empty() == false) { return true;
if (!(yyin = fopen (file.c_str (), "r"))) {
// FIXME: we should return a decent error.
exit (EXIT_FAILURE);
}
} }
return false;
} }
void Driver::scan_end () { void Driver::scan_end () {
if (buffer.empty() == false) {
yy_scan_string(buffer.c_str());
} else if (file.empty() == false) {
fclose(yyin);
}
} }
} }

View File

@ -97,11 +97,11 @@ Rules::~Rules() {
* @retval false Problem loading the rules. * @retval false Problem loading the rules.
* *
*/ */
bool Rules::loadFromUri(char *uri) { bool Rules::loadFromUri(const char *uri) {
Driver *driver = new Driver(); Driver *driver = new Driver();
if (driver->parseFile(uri) == false) { if (driver->parseFile(uri) == false) {
parserError << driver->parserError.rdbuf(); parserError << driver->parserError.str();
return false; return false;
} }
@ -111,6 +111,19 @@ bool Rules::loadFromUri(char *uri) {
return true; return true;
} }
bool Rules::load(const char *file, const std::string &ref) {
Driver *driver = new Driver();
if (driver->parse(file, ref) == false) {
parserError << driver->parserError.str();
return false;
}
this->merge(driver);
delete driver;
return true;
}
bool Rules::loadRemote(char *key, char *uri) { bool Rules::loadRemote(char *key, char *uri) {
HttpsClient client; HttpsClient client;
@ -124,22 +137,8 @@ bool Rules::loadRemote(char *key, char *uri) {
} }
bool Rules::load(const char *plain_rules) { bool Rules::load(const char *plainRules) {
return this->load(plain_rules, ""); return this->load(plainRules, "");
}
bool Rules::load(const char *plain_rules, const std::string &ref) {
Driver *driver = new Driver();
if (driver->parse(plain_rules, ref) == false) {
parserError << driver->parserError.str();
return false;
}
this->merge(driver);
delete driver;
return true;
} }
@ -188,23 +187,20 @@ int Rules::merge(Driver *from) {
this->requestBodyLimitAction = from->requestBodyLimitAction; this->requestBodyLimitAction = from->requestBodyLimitAction;
this->responseBodyLimitAction = from->responseBodyLimitAction; this->responseBodyLimitAction = from->responseBodyLimitAction;
if (m_custom_debug_log) { if (customDebugLog) {
this->debug_log = m_custom_debug_log->new_instance(); this->debugLog = customDebugLog->new_instance();
} else { } else {
this->debug_log = new DebugLog(); this->debugLog = new DebugLog();
} }
this->audit_log = from->audit_log; this->audit_log = from->audit_log;
this->debug_log->setDebugLevel(this->debug_level); this->debugLog->setDebugLevel(this->debug_level);
this->debug_log->setOutputFile(this->debug_log_path); this->debugLog->setOutputFile(this->debug_log_path);
return 0; return 0;
} }
void Rules::debug(int level, std::string message) {
this->debug_log->write_log(level, message);
}
int Rules::merge(Rules *from) { int Rules::merge(Rules *from) {
for (int i = 0; i < ModSecurity::Phases::NUMBER_OF_PHASES; i++) { for (int i = 0; i < ModSecurity::Phases::NUMBER_OF_PHASES; i++) {
@ -226,21 +222,28 @@ int Rules::merge(Rules *from) {
this->requestBodyLimitAction = from->requestBodyLimitAction; this->requestBodyLimitAction = from->requestBodyLimitAction;
this->responseBodyLimitAction = from->responseBodyLimitAction; this->responseBodyLimitAction = from->responseBodyLimitAction;
if (m_custom_debug_log) { if (customDebugLog) {
this->debug_log = m_custom_debug_log->new_instance(); this->debugLog = customDebugLog->new_instance();
} else { } else {
this->debug_log = new DebugLog(); this->debugLog = new DebugLog();
} }
this->audit_log = from->audit_log; this->audit_log = from->audit_log;
this->debug_log->setDebugLevel(this->debug_level); this->debugLog->setDebugLevel(this->debug_level);
this->debug_log->setOutputFile(this->debug_log_path); this->debugLog->setOutputFile(this->debug_log_path);
return 0; return 0;
} }
void Rules::debug(int level, std::string message) {
if (debugLog != NULL) {
debugLog->write_log(level, message);
}
}
void Rules::dump() { void Rules::dump() {
std::cout << "Rules: " << std::endl; std::cout << "Rules: " << std::endl;
for (int i = 0; i < ModSecurity::Phases::NUMBER_OF_PHASES; i++) { for (int i = 0; i < ModSecurity::Phases::NUMBER_OF_PHASES; i++) {

View File

@ -161,7 +161,7 @@ end:
modsec_assay->processLogging(r.status); modsec_assay->processLogging(r.status);
CustomDebugLog *d = reinterpret_cast<CustomDebugLog *> CustomDebugLog *d = reinterpret_cast<CustomDebugLog *>
(modsec_rules->debug_log); (modsec_rules->debugLog);
if (!d->contains(t->debug_log)) { if (!d->contains(t->debug_log)) {
std::cout << "Debug log was not matching the expected results."; std::cout << "Debug log was not matching the expected results.";

View File

@ -0,0 +1,3 @@
Include test-cases/data/config_example2.txt
SecRule ARGS "@contains config_example" "id:10,pass,t:trim"
Include test-cases/data/config_example2.txt

View File

@ -0,0 +1,2 @@
SecRule ARGS "@contains config_example2" "id:20,pass,t:trim"

View File

@ -0,0 +1,256 @@
[
{
"enabled":1,
"version_min":300000,
"title":"Include (1/6)",
"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":"*/*"
},
"uri":"/?key=value&key=other_value",
"protocol":"GET"
},
"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":"Executing operator \"@contains \" with param \"config_example2\" against ARGS."
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"Include test-cases/data/config_example.txt",
"SecRule ARGS \"@contains test\" \"id:9,pass,t:trim\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Include (2/6)",
"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":"*/*"
},
"uri":"/?key=value&key=other_value",
"protocol":"GET"
},
"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":"Executing operator \"@contains \" with param \"config_example\" against ARGS."
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"Include test-cases/data/config_example.txt",
"SecRule ARGS \"@contains test\" \"id:9,pass,t:trim\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Include (3/6)",
"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":"*/*"
},
"uri":"/?key=value&key=other_value",
"protocol":"GET"
},
"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":"Executing operator \"@contains \" with param \"config_example2\" against ARGS."
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"Include test-cases/data/config_example2.txt",
"SecRule ARGS \"@contains test\" \"id:9,pass,t:trim\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Include (4/6)",
"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":"*/*"
},
"uri":"/?key=value&key=other_value",
"protocol":"GET"
},
"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":"Executing operator \"@contains \" with param \"test\" against ARGS."
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"SecRule ARGS \"@contains test\" \"id:9,pass,t:trim\"",
"Include test-cases/data/config_example2.txt"
]
},
{
"enabled":1,
"version_min":300000,
"title":"Include (5/6)",
"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":"*/*"
},
"uri":"/?key=value&key=other_value",
"protocol":"GET"
},
"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":"Executing operator \"@contains \" with param \"config_example2\" against ARGS."
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"SecRule ARGS \"@contains test\" \"id:1,pass,t:trim\"",
"Include test-cases/data/config_example.txt",
"Include test-cases/data/config_example.txt",
"SecRule ARGS \"@contains test\" \"id:3,pass,t:trim\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Include (6/6)",
"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":"*/*"
},
"uri":"/?key=value&key=other_value",
"protocol":"GET"
},
"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":"Executing operator \"@contains \" with param \"test\" against ARGS."
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"Include test-cases/data/config_example2.txt",
"SecRule ARGS \"@contains test\" \"id:9,pass,t:trim\""
]
}
]

View File

@ -0,0 +1,44 @@
[
{
"enabled":1,
"version_min":300000,
"title":"Include",
"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":"*/*"
},
"uri":"/?key=value&key=other_value",
"protocol":"GET"
},
"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":"Executing operator \"@pmfromfile \" with param \"https://www.modsecurity.org/modsecurity-regression-test.txt\" against REQUEST_FILENAME"
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"SecRemoteRules key https://www.modsecurity.org/modsecurity-regression-test-secremoterules.txt",
"SecRule ARGS \"@contains somethingelse\" \"id:9,pass,t:trim\""
]
}
]