mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-15 23:55:03 +03:00
Adds support to BodyLimitAction and support for parser errors
This commit is contained in:
parent
30b2624ec5
commit
261ee9f115
@ -74,6 +74,7 @@ class Rules {
|
|||||||
int merge(Rules *rules);
|
int merge(Rules *rules);
|
||||||
|
|
||||||
int evaluate(int phase, Assay *assay);
|
int evaluate(int phase, Assay *assay);
|
||||||
|
std::string getParserError();
|
||||||
|
|
||||||
std::vector<Rule *> rules[7]; // Number of Phases.
|
std::vector<Rule *> rules[7]; // Number of Phases.
|
||||||
|
|
||||||
@ -101,6 +102,18 @@ class Rules {
|
|||||||
DetectionOnlyRuleEngine
|
DetectionOnlyRuleEngine
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum BodyLimitAction {
|
||||||
|
/**
|
||||||
|
* Process partial
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
ProcessPartialBodyLimitAction,
|
||||||
|
/**
|
||||||
|
* Process partial
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
RejectBodyLimitAction
|
||||||
|
};
|
||||||
static const char *ruleEngineStateString(RuleEngine i) {
|
static const char *ruleEngineStateString(RuleEngine i) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case DisabledRuleEngine:
|
case DisabledRuleEngine:
|
||||||
@ -128,6 +141,11 @@ class Rules {
|
|||||||
|
|
||||||
int requestBodyLimit;
|
int requestBodyLimit;
|
||||||
int responseBodyLimit;
|
int responseBodyLimit;
|
||||||
|
int requestBodyLimitAction;
|
||||||
|
int responseBodyLimitAction;
|
||||||
|
|
||||||
|
std::string parserError;
|
||||||
|
|
||||||
AuditLog *audit_log;
|
AuditLog *audit_log;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
46
src/assay.cc
46
src/assay.cc
@ -31,6 +31,7 @@
|
|||||||
#include "modsecurity/modsecurity.h"
|
#include "modsecurity/modsecurity.h"
|
||||||
#include "modsecurity/intervention.h"
|
#include "modsecurity/intervention.h"
|
||||||
#include "actions/action.h"
|
#include "actions/action.h"
|
||||||
|
#include "actions/block.h"
|
||||||
#include "src/utils.h"
|
#include "src/utils.h"
|
||||||
#include "src/audit_log.h"
|
#include "src/audit_log.h"
|
||||||
#include "src/unique_id.h"
|
#include "src/unique_id.h"
|
||||||
@ -613,6 +614,24 @@ int Assay::appendRequestBody(const unsigned char *buf, size_t len) {
|
|||||||
if (this->m_rules->requestBodyLimit > 0
|
if (this->m_rules->requestBodyLimit > 0
|
||||||
&& this->m_rules->requestBodyLimit < len + current_size) {
|
&& this->m_rules->requestBodyLimit < len + current_size) {
|
||||||
store_variable("INBOUND_DATA_ERROR", "1");
|
store_variable("INBOUND_DATA_ERROR", "1");
|
||||||
|
debug(5, "Rquest body is bigger than the maximum expected.");
|
||||||
|
if (this->m_rules->requestBodyLimitAction ==
|
||||||
|
Rules::BodyLimitAction::ProcessPartialBodyLimitAction) {
|
||||||
|
size_t spaceLeft = this->m_rules->requestBodyLimit - current_size;
|
||||||
|
this->m_requestBody.write(reinterpret_cast<const char*>(buf),
|
||||||
|
spaceLeft);
|
||||||
|
debug(5, "Request body limit is marked to process partial");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (this->m_rules->requestBodyLimitAction ==
|
||||||
|
Rules::BodyLimitAction::RejectBodyLimitAction) {
|
||||||
|
debug(5, "Request body limit is marked to reject the " \
|
||||||
|
"request");
|
||||||
|
Action *a = new actions::Block("block");
|
||||||
|
actions.push_back(a);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->m_requestBody.write(reinterpret_cast<const char*>(buf), len);
|
this->m_requestBody.write(reinterpret_cast<const char*>(buf), len);
|
||||||
@ -778,23 +797,42 @@ int Assay::processResponseBody() {
|
|||||||
*
|
*
|
||||||
* @returns If the operation was successful or not.
|
* @returns If the operation was successful or not.
|
||||||
* @retval true Operation was successful.
|
* @retval true Operation was successful.
|
||||||
* @retval false Operation failed.
|
* @retval false Operation failed, process partial demanded.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int Assay::appendResponseBody(const unsigned char *buf, size_t len) {
|
int Assay::appendResponseBody(const unsigned char *buf, size_t len) {
|
||||||
int current_size = this->m_responseBody.tellp();
|
int current_size = this->m_responseBody.tellp();
|
||||||
|
|
||||||
debug(9, "Appending response body: " + std::to_string(len) + " bytes. " \
|
debug(9, "Appending response body: " + std::to_string(len + current_size)
|
||||||
"Limit set to: " + std::to_string(this->m_rules->responseBodyLimit));
|
+ " bytes. Limit set to: " +
|
||||||
|
std::to_string(this->m_rules->responseBodyLimit));
|
||||||
|
|
||||||
if (this->m_rules->responseBodyLimit > 0
|
if (this->m_rules->responseBodyLimit > 0
|
||||||
&& this->m_rules->responseBodyLimit < len + current_size) {
|
&& this->m_rules->responseBodyLimit < len + current_size) {
|
||||||
store_variable("OUTBOUND_DATA_ERROR", "1");
|
store_variable("OUTBOUND_DATA_ERROR", "1");
|
||||||
|
debug(5, "Response body is bigger than the maximum expected.");
|
||||||
|
if (this->m_rules->responseBodyLimitAction ==
|
||||||
|
Rules::BodyLimitAction::ProcessPartialBodyLimitAction) {
|
||||||
|
size_t spaceLeft = this->m_rules->responseBodyLimit - current_size;
|
||||||
|
this->m_responseBody.write(reinterpret_cast<const char*>(buf),
|
||||||
|
spaceLeft);
|
||||||
|
debug(5, "Response body limit is marked to process partial");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (this->m_rules->responseBodyLimitAction ==
|
||||||
|
Rules::BodyLimitAction::RejectBodyLimitAction) {
|
||||||
|
debug(5, "Response body limit is marked to reject the " \
|
||||||
|
"request");
|
||||||
|
Action *a = new actions::Block("block");
|
||||||
|
actions.push_back(a);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->m_responseBody.write(reinterpret_cast<const char*>(buf), len);
|
this->m_responseBody.write(reinterpret_cast<const char*>(buf), len);
|
||||||
|
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,8 +74,7 @@ int Driver::parse(const std::string &f) {
|
|||||||
|
|
||||||
int res = parser.parse();
|
int res = parser.parse();
|
||||||
|
|
||||||
if (this->audit_log->init() == false)
|
if (this->audit_log->init() == false) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,11 +97,18 @@ int Driver::parseFile(const std::string &f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Driver::error(const yy::location& l, const std::string& m) {
|
void Driver::error(const yy::location& l, const std::string& m,
|
||||||
std::cerr << l << ": " << m << std::endl;
|
const std::string& c) {
|
||||||
|
if (parserError.tellp() == 0) {
|
||||||
|
parserError << "Parser error, ";
|
||||||
|
parserError << "Filename: " << file << ". ";
|
||||||
|
parserError << "Line: " << l.end.line << ". ";
|
||||||
|
parserError << "Column: " << l.end.column << ". ";
|
||||||
|
}
|
||||||
|
parserError << c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Driver::error(const std::string& m) {
|
void Driver::parser_error(const yy::location& l, const std::string& m) {
|
||||||
std::cerr << m << std::endl;
|
parserError << ". " << m << "." << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,8 @@ class Driver {
|
|||||||
|
|
||||||
// Error handling.
|
// Error handling.
|
||||||
void error(const yy::location& l, const std::string& m);
|
void error(const yy::location& l, const std::string& m);
|
||||||
void error(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, const std::string& c);
|
||||||
|
|
||||||
std::vector<Rule *> rules[7]; // Number of Phases.
|
std::vector<Rule *> rules[7]; // Number of Phases.
|
||||||
|
|
||||||
@ -89,9 +90,13 @@ class Driver {
|
|||||||
bool sec_response_body_access;
|
bool sec_response_body_access;
|
||||||
int requestBodyLimit;
|
int requestBodyLimit;
|
||||||
int responseBodyLimit;
|
int responseBodyLimit;
|
||||||
|
int requestBodyLimitAction;
|
||||||
|
int responseBodyLimitAction;
|
||||||
|
|
||||||
std::string debug_log_path;
|
std::string debug_log_path;
|
||||||
std::list<std::string> components;
|
std::list<std::string> components;
|
||||||
|
std::ostringstream parserError;
|
||||||
|
std::ostringstream syntaxError;
|
||||||
|
|
||||||
ModSecurity::AuditLog *audit_log;
|
ModSecurity::AuditLog *audit_log;
|
||||||
|
|
||||||
|
@ -73,7 +73,6 @@ using ModSecurity::Variables::TimeYear;
|
|||||||
QUOTATION_MARK ")"
|
QUOTATION_MARK ")"
|
||||||
SPACE
|
SPACE
|
||||||
PIPE
|
PIPE
|
||||||
NEW_LINE
|
|
||||||
UNKNOWN
|
UNKNOWN
|
||||||
FREE_TEXT
|
FREE_TEXT
|
||||||
;
|
;
|
||||||
@ -83,6 +82,8 @@ using ModSecurity::Variables::TimeYear;
|
|||||||
%token <std::string> CONFIG_DIRECTIVE
|
%token <std::string> CONFIG_DIRECTIVE
|
||||||
%token <std::string> CONFIG_DIR_REQ_BODY_LIMIT
|
%token <std::string> CONFIG_DIR_REQ_BODY_LIMIT
|
||||||
%token <std::string> CONFIG_DIR_RES_BODY_LIMIT
|
%token <std::string> CONFIG_DIR_RES_BODY_LIMIT
|
||||||
|
%token <std::string> CONFIG_DIR_REQ_BODY_LIMIT_ACTION
|
||||||
|
%token <std::string> CONFIG_DIR_RES_BODY_LIMIT_ACTION
|
||||||
%token <std::string> CONFIG_DIR_RULE_ENG
|
%token <std::string> CONFIG_DIR_RULE_ENG
|
||||||
%token <std::string> CONFIG_DIR_REQ_BODY
|
%token <std::string> CONFIG_DIR_REQ_BODY
|
||||||
%token <std::string> CONFIG_DIR_RES_BODY
|
%token <std::string> CONFIG_DIR_RES_BODY
|
||||||
@ -93,6 +94,8 @@ using ModSecurity::Variables::TimeYear;
|
|||||||
%token <std::string> CONFIG_VALUE_SERIAL
|
%token <std::string> CONFIG_VALUE_SERIAL
|
||||||
%token <std::string> CONFIG_VALUE_PARALLEL
|
%token <std::string> CONFIG_VALUE_PARALLEL
|
||||||
%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_REJECT
|
||||||
|
|
||||||
%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
|
||||||
@ -146,11 +149,12 @@ secrule:
|
|||||||
| secrule line
|
| secrule line
|
||||||
|
|
||||||
line:
|
line:
|
||||||
expression NEW_LINE
|
expression
|
||||||
| SPACE expression NEW_LINE
|
| SPACE expression
|
||||||
| NEW_LINE
|
|
||||||
| SPACE NEW_LINE
|
|
||||||
| SPACE
|
| SPACE
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
audit_log:
|
audit_log:
|
||||||
/* SecAuditLogDirMode */
|
/* SecAuditLogDirMode */
|
||||||
@ -280,6 +284,7 @@ expression:
|
|||||||
{
|
{
|
||||||
GeoLookup::getInstance().setDataBase($1);
|
GeoLookup::getInstance().setDataBase($1);
|
||||||
}
|
}
|
||||||
|
/* Body limits */
|
||||||
| CONFIG_DIR_REQ_BODY_LIMIT
|
| CONFIG_DIR_REQ_BODY_LIMIT
|
||||||
{
|
{
|
||||||
driver.requestBodyLimit = atoi($1.c_str());
|
driver.requestBodyLimit = atoi($1.c_str());
|
||||||
@ -288,6 +293,22 @@ expression:
|
|||||||
{
|
{
|
||||||
driver.responseBodyLimit = atoi($1.c_str());
|
driver.responseBodyLimit = atoi($1.c_str());
|
||||||
}
|
}
|
||||||
|
| CONFIG_DIR_REQ_BODY_LIMIT_ACTION SPACE CONFIG_VALUE_PROCESS_PARTIAL
|
||||||
|
{
|
||||||
|
driver.requestBodyLimitAction = ModSecurity::Rules::BodyLimitAction::ProcessPartialBodyLimitAction;
|
||||||
|
}
|
||||||
|
| CONFIG_DIR_REQ_BODY_LIMIT_ACTION SPACE CONFIG_VALUE_REJECT
|
||||||
|
{
|
||||||
|
driver.requestBodyLimitAction = ModSecurity::Rules::BodyLimitAction::RejectBodyLimitAction;
|
||||||
|
}
|
||||||
|
| CONFIG_DIR_RES_BODY_LIMIT_ACTION SPACE CONFIG_VALUE_PROCESS_PARTIAL
|
||||||
|
{
|
||||||
|
driver.responseBodyLimitAction = ModSecurity::Rules::BodyLimitAction::ProcessPartialBodyLimitAction;
|
||||||
|
}
|
||||||
|
| CONFIG_DIR_RES_BODY_LIMIT_ACTION SPACE CONFIG_VALUE_REJECT
|
||||||
|
{
|
||||||
|
driver.responseBodyLimitAction = ModSecurity::Rules::BodyLimitAction::RejectBodyLimitAction;
|
||||||
|
}
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
variables PIPE VARIABLE
|
variables PIPE VARIABLE
|
||||||
@ -544,5 +565,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.error (l, m);
|
driver.parser_error (l, m);
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,16 @@
|
|||||||
static yy::location loc;
|
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]+|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|t)
|
ACTION (?i:accuracy|allow|append|auditlog|block|capture|chain|ctl|deny|deprecatevar|drop|exec|expirevar|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
|
||||||
|
|
||||||
CONFIG_DIRECTIVE SecRequestBodyLimitAction|SecRequestBodyNoFilesLimit|SecRequestBodyInMemoryLimit|SecPcreMatchLimitRecursion|SecPcreMatchLimit|SecResponseBodyMimeType|SecResponseBodyLimitAction|SecTmpDir|SecDataDir|SecArgumentSeparator|SecCookieFormat|SecStatusEngine
|
CONFIG_DIRECTIVE SecRequestBodyNoFilesLimit|SecRequestBodyInMemoryLimit|SecPcreMatchLimitRecursion|SecPcreMatchLimit|SecResponseBodyMimeType|SecTmpDir|SecDataDir|SecArgumentSeparator|SecCookieFormat|SecStatusEngine
|
||||||
|
|
||||||
CONFIG_DIR_REQ_BODY_LIMIT (?i:SecRequestBodyLimit)
|
CONFIG_DIR_REQ_BODY_LIMIT (?i:SecRequestBodyLimit)
|
||||||
CONFIG_DIR_RES_BODY_LIMIT (?i:SecResponseBodyLimit)
|
CONFIG_DIR_RES_BODY_LIMIT (?i:SecResponseBodyLimit)
|
||||||
|
CONFIG_DIR_REQ_BODY_LIMIT_ACTION (?i:SecRequestBodyLimitAction)
|
||||||
|
CONFIG_DIR_RES_BODY_LIMIT_ACTION (?i:SecResponseBodyLimitAction)
|
||||||
|
|
||||||
CONFIG_DIR_GEO_DB (?i:SecGeoLookupDb)
|
CONFIG_DIR_GEO_DB (?i:SecGeoLookupDb)
|
||||||
|
|
||||||
@ -85,6 +87,10 @@ CONFIG_VALUE_SERIAL Serial
|
|||||||
CONFIG_VALUE_PARALLEL Parallel
|
CONFIG_VALUE_PARALLEL Parallel
|
||||||
CONFIG_VALUE_RELEVANT_ONLY RelevantOnly
|
CONFIG_VALUE_RELEVANT_ONLY RelevantOnly
|
||||||
|
|
||||||
|
CONFIG_VALUE_PROCESS_PARTIAL (?i:ProcessPartial)
|
||||||
|
CONFIG_VALUE_REJECT (?i:Reject)
|
||||||
|
|
||||||
|
|
||||||
CONFIG_VALUE_PATH [A-Za-z_/\.]+
|
CONFIG_VALUE_PATH [A-Za-z_/\.]+
|
||||||
AUDIT_PARTS [ABCDEFHJKZ]+
|
AUDIT_PARTS [ABCDEFHJKZ]+
|
||||||
CONFIG_VALUE_NUMBER [0-9]+
|
CONFIG_VALUE_NUMBER [0-9]+
|
||||||
@ -101,7 +107,7 @@ FREE_TEXT_NEW_LINE [^\"|\n]+
|
|||||||
|
|
||||||
%{
|
%{
|
||||||
// Code run each time yylex is called.
|
// Code run each time yylex is called.
|
||||||
loc.step ();
|
loc.step();
|
||||||
%}
|
%}
|
||||||
|
|
||||||
{DIRECTIVE} { return yy::seclang_parser::make_DIRECTIVE(yytext, loc); }
|
{DIRECTIVE} { return yy::seclang_parser::make_DIRECTIVE(yytext, loc); }
|
||||||
@ -148,8 +154,10 @@ FREE_TEXT_NEW_LINE [^\"|\n]+
|
|||||||
|
|
||||||
%{ /* 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, loc); }
|
||||||
|
{CONFIG_DIR_REQ_BODY_LIMIT_ACTION} { return yy::seclang_parser::make_CONFIG_DIR_REQ_BODY_LIMIT_ACTION(yytext, 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, loc); }
|
||||||
|
{CONFIG_DIR_RES_BODY_LIMIT_ACTION} { return yy::seclang_parser::make_CONFIG_DIR_RES_BODY_LIMIT_ACTION(yytext, 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, loc); }
|
||||||
|
|
||||||
@ -159,6 +167,9 @@ FREE_TEXT_NEW_LINE [^\"|\n]+
|
|||||||
{CONFIG_VALUE_PARALLEL} { return yy::seclang_parser::make_CONFIG_VALUE_PARALLEL(yytext, loc); }
|
{CONFIG_VALUE_PARALLEL} { return yy::seclang_parser::make_CONFIG_VALUE_PARALLEL(yytext, loc); }
|
||||||
{CONFIG_VALUE_DETC} { return yy::seclang_parser::make_CONFIG_VALUE_DETC(yytext, loc); }
|
{CONFIG_VALUE_DETC} { return yy::seclang_parser::make_CONFIG_VALUE_DETC(yytext, loc); }
|
||||||
{CONFIG_VALUE_RELEVANT_ONLY} { return yy::seclang_parser::make_CONFIG_VALUE_RELEVANT_ONLY(yytext, loc); }
|
{CONFIG_VALUE_RELEVANT_ONLY} { return yy::seclang_parser::make_CONFIG_VALUE_RELEVANT_ONLY(yytext, loc); }
|
||||||
|
{CONFIG_VALUE_PROCESS_PARTIAL} { return yy::seclang_parser::make_CONFIG_VALUE_PROCESS_PARTIAL(yytext, loc); }
|
||||||
|
{CONFIG_VALUE_REJECT} { return yy::seclang_parser::make_CONFIG_VALUE_REJECT(yytext, loc); }
|
||||||
|
|
||||||
["]{OPERATOR}[ ]{FREE_TEXT}["] { return yy::seclang_parser::make_OPERATOR(yytext, loc); }
|
["]{OPERATOR}[ ]{FREE_TEXT}["] { return yy::seclang_parser::make_OPERATOR(yytext, loc); }
|
||||||
["]{OPERATORNOARG}["] { 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} { return yy::seclang_parser::make_ACTION(yytext, loc); }
|
||||||
@ -168,8 +179,8 @@ FREE_TEXT_NEW_LINE [^\"|\n]+
|
|||||||
[|] { return yy::seclang_parser::make_PIPE(loc); }
|
[|] { return yy::seclang_parser::make_PIPE(loc); }
|
||||||
{VARIABLENOCOLON} { return yy::seclang_parser::make_VARIABLE(yytext, loc); }
|
{VARIABLENOCOLON} { return yy::seclang_parser::make_VARIABLE(yytext, loc); }
|
||||||
[ \t]+ { return yy::seclang_parser::make_SPACE(loc); }
|
[ \t]+ { return yy::seclang_parser::make_SPACE(loc); }
|
||||||
\n { return yy::seclang_parser::make_NEW_LINE(loc); }
|
[\n]+ { loc.lines(yyleng); loc.step(); }
|
||||||
. driver.error (loc, "invalid character");
|
. { driver.error (loc, "invalid character", yytext); }
|
||||||
<<EOF>> { return yy::seclang_parser::make_END(loc); }
|
<<EOF>> { return yy::seclang_parser::make_END(loc); }
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
10
src/rules.cc
10
src/rules.cc
@ -124,6 +124,7 @@ int Rules::load(const char *plain_rules) {
|
|||||||
Driver *driver = new Driver();
|
Driver *driver = new Driver();
|
||||||
if (driver->parse("/tmp/modsec_ugly_hack.txt")) {
|
if (driver->parse("/tmp/modsec_ugly_hack.txt")) {
|
||||||
ret = false;
|
ret = false;
|
||||||
|
parserError = driver->parserError.str();
|
||||||
}
|
}
|
||||||
this->merge(driver);
|
this->merge(driver);
|
||||||
delete driver;
|
delete driver;
|
||||||
@ -132,6 +133,11 @@ int Rules::load(const char *plain_rules) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string Rules::getParserError() {
|
||||||
|
return this->parserError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int Rules::evaluate(int phase, Assay *assay) {
|
int Rules::evaluate(int phase, Assay *assay) {
|
||||||
if (phase > ModSecurity::Phases::NUMBER_OF_PHASES) {
|
if (phase > ModSecurity::Phases::NUMBER_OF_PHASES) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -169,6 +175,8 @@ int Rules::merge(Driver *from) {
|
|||||||
this->components = from->components;
|
this->components = from->components;
|
||||||
this->requestBodyLimit = from->requestBodyLimit;
|
this->requestBodyLimit = from->requestBodyLimit;
|
||||||
this->responseBodyLimit = from->responseBodyLimit;
|
this->responseBodyLimit = from->responseBodyLimit;
|
||||||
|
this->requestBodyLimitAction = from->requestBodyLimitAction;
|
||||||
|
this->responseBodyLimitAction = from->responseBodyLimitAction;
|
||||||
|
|
||||||
if (m_custom_debug_log) {
|
if (m_custom_debug_log) {
|
||||||
this->debug_log = m_custom_debug_log->new_instance();
|
this->debug_log = m_custom_debug_log->new_instance();
|
||||||
@ -205,6 +213,8 @@ int Rules::merge(Rules *from) {
|
|||||||
this->components = from->components;
|
this->components = from->components;
|
||||||
this->requestBodyLimit = from->requestBodyLimit;
|
this->requestBodyLimit = from->requestBodyLimit;
|
||||||
this->responseBodyLimit = from->responseBodyLimit;
|
this->responseBodyLimit = from->responseBodyLimit;
|
||||||
|
this->requestBodyLimitAction = from->requestBodyLimitAction;
|
||||||
|
this->responseBodyLimitAction = from->responseBodyLimitAction;
|
||||||
|
|
||||||
this->debug_log = from->debug_log;
|
this->debug_log = from->debug_log;
|
||||||
|
|
||||||
|
205
test/test-cases/regression/config-body_limits.json
Normal file
205
test/test-cases/regression/config-body_limits.json
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"title":"SecResponseBodyLimitAction Reject",
|
||||||
|
"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":{
|
||||||
|
"http_code":403
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleEngine On",
|
||||||
|
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||||
|
"SecDebugLogLevel 9",
|
||||||
|
"SecResponseBodyLimitAction Reject",
|
||||||
|
"SecResponseBodyLimit 5"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"title":"SecResponseBodyLimitAction ProcessPartial",
|
||||||
|
"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":{
|
||||||
|
"http_code":200
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleEngine On",
|
||||||
|
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||||
|
"SecDebugLogLevel 9",
|
||||||
|
"SecResponseBodyLimitAction ProcessPartial",
|
||||||
|
"SecResponseBodyLimit 5"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"title":"SecRequestBodyLimitAction Reject",
|
||||||
|
"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":"POST",
|
||||||
|
"body":[
|
||||||
|
"--------------------------756b6d74fa1a8ee2",
|
||||||
|
"Content-Disposition: form-data; name=\"name\"",
|
||||||
|
"",
|
||||||
|
"test",
|
||||||
|
"--------------------------756b6d74fa1a8ee2",
|
||||||
|
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
|
||||||
|
"Content-Type: text/plain",
|
||||||
|
"",
|
||||||
|
"This is a very small test file..",
|
||||||
|
"--------------------------756b6d74fa1a8ee2",
|
||||||
|
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
|
||||||
|
"Content-Type: text/plain",
|
||||||
|
"",
|
||||||
|
"This is another very small test file..",
|
||||||
|
"--------------------------756b6d74fa1a8ee2--"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"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":{
|
||||||
|
"http_code":403
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleEngine On",
|
||||||
|
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||||
|
"SecDebugLogLevel 9",
|
||||||
|
"SecRequestBodyLimitAction Reject",
|
||||||
|
"SecRequestBodyLimit 5"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled":1,
|
||||||
|
"version_min":300000,
|
||||||
|
"title":"SecRequestBodyLimitAction ProcessPartial",
|
||||||
|
"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":"POST",
|
||||||
|
"body":[
|
||||||
|
"--------------------------756b6d74fa1a8ee2",
|
||||||
|
"Content-Disposition: form-data; name=\"name\"",
|
||||||
|
"",
|
||||||
|
"test",
|
||||||
|
"--------------------------756b6d74fa1a8ee2",
|
||||||
|
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
|
||||||
|
"Content-Type: text/plain",
|
||||||
|
"",
|
||||||
|
"This is a very small test file..",
|
||||||
|
"--------------------------756b6d74fa1a8ee2",
|
||||||
|
"Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"",
|
||||||
|
"Content-Type: text/plain",
|
||||||
|
"",
|
||||||
|
"This is another very small test file..",
|
||||||
|
"--------------------------756b6d74fa1a8ee2--"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"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":{
|
||||||
|
"http_code":200
|
||||||
|
},
|
||||||
|
"rules":[
|
||||||
|
"SecRuleEngine On",
|
||||||
|
"SecDebugLog \/tmp\/modsec_debug.log",
|
||||||
|
"SecDebugLogLevel 9",
|
||||||
|
"SecRequestBodyLimitAction ProcessPartial",
|
||||||
|
"SecRequestBodyLimit 5"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user