Adds support to BodyLimitAction and support for parser errors

This commit is contained in:
Felipe Zimmerle 2015-07-22 20:55:17 -03:00
parent 30b2624ec5
commit 261ee9f115
8 changed files with 337 additions and 23 deletions

View File

@ -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:

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;

View File

@ -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);
} }

View File

@ -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); }
%% %%

View File

@ -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;

View 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"
]
}
]