mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-13 13:26:01 +03:00
Adds support to the allow action
This commit is contained in:
parent
e77e4c4c14
commit
f72bd587ec
@ -224,4 +224,5 @@ TESTS+=test/test-cases/regression/variable-SERVER_NAME.json
|
||||
TESTS+=test/test-cases/regression/operator-UnconditionalMatch.json
|
||||
TESTS+=test/test-cases/regression/request-body-parser-json.json
|
||||
TESTS+=test/test-cases/regression/action-skip.json
|
||||
TESTS+=test/test-cases/regression/action-allow.json
|
||||
|
||||
|
@ -73,6 +73,7 @@ class Rules;
|
||||
class RuleMessage;
|
||||
namespace actions {
|
||||
class Action;
|
||||
enum AllowType : short;
|
||||
}
|
||||
namespace RequestBodyProcessor {
|
||||
class XML;
|
||||
@ -310,6 +311,11 @@ class Transaction {
|
||||
*/
|
||||
int m_skip_next;
|
||||
|
||||
/**
|
||||
* If allow action was utilized, this variable holds the allow type.
|
||||
*/
|
||||
modsecurity::actions::AllowType m_allowType;
|
||||
|
||||
/**
|
||||
* Holds the decode URI. Notice that m_uri holds the raw version
|
||||
* of the URI.
|
||||
|
@ -78,6 +78,7 @@ VARIABLES = \
|
||||
ACTIONS = \
|
||||
actions/accuracy.cc \
|
||||
actions/action.cc \
|
||||
actions/allow.cc \
|
||||
actions/audit_log.cc \
|
||||
actions/block.cc \
|
||||
actions/capture.cc \
|
||||
|
58
src/actions/allow.cc
Normal file
58
src/actions/allow.cc
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "actions/allow.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "modsecurity/transaction.h"
|
||||
#include "modsecurity/rule.h"
|
||||
#include "src/utils.h"
|
||||
#include "modsecurity/modsecurity.h"
|
||||
|
||||
namespace modsecurity {
|
||||
namespace actions {
|
||||
|
||||
bool Allow::init(std::string *error) {
|
||||
std::string a = tolower(m_parser_payload);
|
||||
|
||||
if (a == "phase") {
|
||||
m_allowType = PhaseAllowType;
|
||||
} else if (a == "request") {
|
||||
m_allowType = RequestAllowType;
|
||||
} else if (a == "") {
|
||||
m_allowType = FromNowOneAllowType;
|
||||
} else {
|
||||
error->assign("Allow: if specified, the parameter most be: phase, request");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Allow::evaluate(Rule *rule, Transaction *transaction) {
|
||||
transaction->debug(4, "Dropping the evaluation of upcoming rules " \
|
||||
"in favor of an `allow' action of type: " \
|
||||
+ allowTypeToName(m_allowType));
|
||||
|
||||
transaction->m_allowType = m_allowType;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace actions
|
||||
} // namespace modsecurity
|
83
src/actions/allow.h
Normal file
83
src/actions/allow.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "actions/action.h"
|
||||
|
||||
#ifndef SRC_ACTIONS_ALLOW_H_
|
||||
#define SRC_ACTIONS_ALLOW_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
class Transaction;
|
||||
|
||||
namespace modsecurity {
|
||||
class Transaction;
|
||||
class Rule;
|
||||
|
||||
namespace actions {
|
||||
|
||||
enum AllowType : short {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
NoneAllowType,
|
||||
/**
|
||||
*
|
||||
*/
|
||||
RequestAllowType,
|
||||
/**
|
||||
*
|
||||
*/
|
||||
PhaseAllowType,
|
||||
/**
|
||||
*
|
||||
*/
|
||||
FromNowOneAllowType,
|
||||
};
|
||||
|
||||
|
||||
class Allow : public Action {
|
||||
public:
|
||||
explicit Allow(std::string action)
|
||||
: Action(action, RunTimeOnlyIfMatchKind),
|
||||
m_allowType(NoneAllowType) { }
|
||||
|
||||
|
||||
bool init(std::string *error) override;
|
||||
bool evaluate(Rule *rule, Transaction *transaction) override;
|
||||
|
||||
AllowType m_allowType;
|
||||
|
||||
static std::string allowTypeToName (AllowType a) {
|
||||
if (a == NoneAllowType) {
|
||||
return "None";
|
||||
} else if (a = RequestAllowType) {
|
||||
return "Request";
|
||||
} else if (a = PhaseAllowType) {
|
||||
return "Phase";
|
||||
} else if (a = FromNowOneAllowType) {
|
||||
return "FromNowOne";
|
||||
} else {
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace actions
|
||||
} // namespace modsecurity
|
||||
#endif
|
||||
|
||||
#endif // SRC_ACTIONS_ALLOW_H_
|
@ -34,6 +34,7 @@ class Driver;
|
||||
#include "actions/skip_after.h"
|
||||
#include "actions/msg.h"
|
||||
#include "actions/phase.h"
|
||||
#include "actions/allow.h"
|
||||
#include "actions/log_data.h"
|
||||
#include "actions/maturity.h"
|
||||
#include "actions/redirect.h"
|
||||
@ -87,6 +88,7 @@ using modsecurity::actions::Rev;
|
||||
using modsecurity::actions::Ver;
|
||||
using modsecurity::actions::Msg;
|
||||
using modsecurity::actions::Phase;
|
||||
using modsecurity::actions::Allow;
|
||||
using modsecurity::actions::transformations::None;
|
||||
using modsecurity::actions::LogData;
|
||||
using modsecurity::actions::Maturity;
|
||||
@ -932,6 +934,15 @@ act:
|
||||
YYERROR;
|
||||
}
|
||||
}
|
||||
| ACTION_ALLOW
|
||||
{
|
||||
std::string error;
|
||||
$$ = new Allow($1);
|
||||
if ($$->init(&error) == false) {
|
||||
driver.error(@0, error);
|
||||
YYERROR;
|
||||
}
|
||||
}
|
||||
| ACTION_PHASE
|
||||
{
|
||||
std::string error;
|
||||
@ -986,24 +997,6 @@ act:
|
||||
*/
|
||||
$$ = Action::instantiate($1);
|
||||
}
|
||||
| ACTION_ALLOW
|
||||
{
|
||||
/*
|
||||
|
||||
TODO: allow is not implemented yet.
|
||||
|
||||
std::string error;
|
||||
Allow *allow = new Allow($1);
|
||||
|
||||
if (allow->init(&error) == false) {
|
||||
driver.parserError << error;
|
||||
YYERROR;
|
||||
}
|
||||
|
||||
$$ = allow;
|
||||
*/
|
||||
$$ = Action::instantiate($1);
|
||||
}
|
||||
| ACTION_REDIRECT
|
||||
{
|
||||
std::string error;
|
||||
|
@ -25,7 +25,7 @@ using modsecurity::split;
|
||||
|
||||
ACTION (?i:accuracy|append|block|capture|chain|deny|deprecatevar|drop|expirevar|id:[0-9]+|id:'[0-9]+'|log|multiMatch|noauditlog|nolog|pass|pause|prepend|proxy|sanitiseArg|sanitiseMatched|sanitiseMatchedBytes|sanitiseRequestHeader|sanitiseResponseHeader|setrsc|setenv|status:[0-9]+)
|
||||
ACTION_XMLNS (?i:xmlns)
|
||||
ACTION_ALLOW (?i:allow)
|
||||
ACTION_ALLOW ((?i:allow:(?i:REQUEST|PHASE))|(?i:phase:'(?i:REQUEST|PHASE)')|(?i:allow))
|
||||
ACTION_INITCOL (?i:initcol)
|
||||
|
||||
ACTION_ACCURACY (?i:accuracy)
|
||||
@ -418,9 +418,7 @@ CONFIG_DIR_UNICODE_MAP_FILE (?i:SecUnicodeMapFile)
|
||||
|
||||
{LOG_DATA}:'{FREE_TEXT_QUOTE}' { return yy::seclang_parser::make_LOG_DATA(yytext, *driver.loc.back()); }
|
||||
{ACTION_MSG}:'{FREE_TEXT_QUOTE}' { return yy::seclang_parser::make_ACTION_MSG(yytext, *driver.loc.back()); }
|
||||
{ACTION_ALLOW}:'{FREE_TEXT_QUOTE}' { return yy::seclang_parser::make_ACTION_ALLOW(yytext, *driver.loc.back()); }
|
||||
{ACTION_ALLOW}:{FREE_TEXT_QUOTE_COMMA} { return yy::seclang_parser::make_ACTION_ALLOW(yytext, *driver.loc.back()); }
|
||||
{ACTION_ALLOW} { return yy::seclang_parser::make_ACTION_ALLOW("", *driver.loc.back()); }
|
||||
{ACTION_ALLOW} { return yy::seclang_parser::make_ACTION_ALLOW(yytext, *driver.loc.back()); }
|
||||
{ACTION_REDIRECT}:{FREE_TEXT} { return yy::seclang_parser::make_ACTION_REDIRECT(yytext, *driver.loc.back()); }
|
||||
{ACTION_TAG}:'{FREE_TEXT_QUOTE}' { return yy::seclang_parser::make_ACTION_TAG(yytext, *driver.loc.back()); }
|
||||
{ACTION_REV}:'{FREE_TEXT_QUOTE_COMMA}' { return yy::seclang_parser::make_ACTION_REV(yytext, *driver.loc.back()); }
|
||||
|
21
src/rules.cc
21
src/rules.cc
@ -183,6 +183,22 @@ int Rules::evaluate(int phase, Transaction *transaction) {
|
||||
debug(9, "This phase consists of " + std::to_string(rules.size()) + \
|
||||
" rule(s).");
|
||||
|
||||
if (transaction->m_allowType == actions::FromNowOneAllowType
|
||||
&& phase != ModSecurity::Phases::LoggingPhase) {
|
||||
debug(9, "Skipping all rules evaluation on this phase as request " \
|
||||
"through the utilization of an `allow' action.");
|
||||
return true;
|
||||
}
|
||||
if (transaction->m_allowType == actions::RequestAllowType
|
||||
&& phase <= ModSecurity::Phases::RequestBodyPhase) {
|
||||
debug(9, "Skipping all rules evaluation on this phase as request " \
|
||||
"through the utilization of an `allow' action.");
|
||||
return true;
|
||||
}
|
||||
if (transaction->m_allowType != actions::NoneAllowType) {
|
||||
transaction->m_allowType = actions::NoneAllowType;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rules.size(); i++) {
|
||||
Rule *rule = rules[i];
|
||||
if (transaction->m_marker.empty() == false) {
|
||||
@ -199,8 +215,11 @@ int Rules::evaluate(int phase, Transaction *transaction) {
|
||||
} else if (transaction->m_skip_next > 0) {
|
||||
transaction->m_skip_next--;
|
||||
debug(9, "Skipped rule id '" + std::to_string(rule->rule_id) \
|
||||
+ "' due to `skip' action. Still " + \
|
||||
+ "' due to a `skip' action. Still " + \
|
||||
std::to_string(transaction->m_skip_next) + " to be skipped.");
|
||||
} else if (transaction->m_allowType != actions::NoneAllowType) {
|
||||
debug(9, "Skipped rule id '" + std::to_string(rule->rule_id) \
|
||||
+ "' as request trough the utilization of an `allow' action.");
|
||||
} else {
|
||||
rule->evaluate(transaction);
|
||||
}
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "src/unique_id.h"
|
||||
#include "src/utils.h"
|
||||
#include "modsecurity/rule.h"
|
||||
#include "src/actions/allow.h"
|
||||
|
||||
using modsecurity::actions::Action;
|
||||
using modsecurity::RequestBodyProcessor::Multipart;
|
||||
@ -113,6 +114,7 @@ Transaction::Transaction(ModSecurity *ms, Rules *rules, void *logCbData)
|
||||
m_responseHeadersNames(NULL),
|
||||
m_responseContentType(NULL),
|
||||
m_marker(""),
|
||||
m_allowType(modsecurity::actions::NoneAllowType),
|
||||
m_skip_next(0),
|
||||
m_creationTimeStamp(cpu_seconds()),
|
||||
m_logCbData(logCbData),
|
||||
|
101
test/test-cases/regression/action-allow.json
Normal file
101
test/test-cases/regression/action-allow.json
Normal file
@ -0,0 +1,101 @@
|
||||
[
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing allow action 1/3",
|
||||
"expected":{
|
||||
"debug_log": "Skipped rule id '500066' as request trough the utilization of an `allow' action",
|
||||
"http_code": 200
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"User-Agent":"My sweet little browser",
|
||||
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120"
|
||||
},
|
||||
"uri":"/?key=value&key=other_value",
|
||||
"method":"GET"
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecAction \"phase:1,allow,msg:'ALLOWED',id:500065\"",
|
||||
"SecAction \"phase:1,deny,msg:'DENIED',id:500066\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing allow action 1/3",
|
||||
"expected":{
|
||||
"debug_log": "",
|
||||
"http_code": 500
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"User-Agent":"My sweet little browser",
|
||||
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120"
|
||||
},
|
||||
"uri":"/?key=value&key=other_value",
|
||||
"method":"GET"
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecAction \"phase:1,allow:request,msg:'ALLOWED',id:500065\"",
|
||||
"SecRule ARGS \"@contains value\" \"id:1,t:trim,status:500,deny,phase:3\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing allow action 1/3",
|
||||
"expected":{
|
||||
"debug_log": "",
|
||||
"http_code": 500
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"User-Agent":"My sweet little browser",
|
||||
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120"
|
||||
},
|
||||
"uri":"/?key=value&key=other_value",
|
||||
"method":"GET"
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecAction \"phase:1,allow:phase,msg:'ALLOWED',id:500065\"",
|
||||
"SecRule ARGS \"@contains value\" \"id:1,t:trim,status:500,deny,phase:3\""
|
||||
]
|
||||
}
|
||||
]
|
@ -4,7 +4,7 @@
|
||||
"version_min":300000,
|
||||
"title":"Testing skip action 1/3",
|
||||
"expected":{
|
||||
"debug_log": "\\[9\\] Skipped rule id \\'2\\' due to \\`skip\\' action."
|
||||
"debug_log": "\\[9\\] Skipped rule id \\'2\\' due to a \\`skip\\' action."
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
@ -74,7 +74,7 @@
|
||||
"version_min":300000,
|
||||
"title":"Testing skip action 3/3",
|
||||
"expected":{
|
||||
"debug_log": "\\[9\\] Skipped rule id \\'3\\' due to \\`skip\\' action."
|
||||
"debug_log": "\\[9\\] Skipped rule id \\'3\\' due to a \\`skip\\' action."
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
|
Loading…
x
Reference in New Issue
Block a user