Implement id ranges for ctl:ruleRemoveTargetById

This commit is contained in:
martinhsv 2020-10-21 13:55:46 -07:00 committed by Felipe Zimmerle
parent abf59f4b84
commit 1f350296ba
No known key found for this signature in database
GPG Key ID: E6DFB08CE8B11277
6 changed files with 225 additions and 8 deletions

View File

@ -1,6 +1,8 @@
v3.x.y - YYYY-MMM-DD (to be released)
-------------------------------------
- Implement id ranges for ctl:ruleRemoveTargetById
[#2110 - @j0k2r, @martinhsv]
- Removed unnecessary while processing the transformations.
[#2368 - @WGH-, @zimmerle]
- auditlog: Computes whether or not to save while loading the rules.

View File

@ -545,6 +545,7 @@ class Transaction : public TransactionAnchoredVariables, public TransactionSecMa
*
*/
std::list< std::pair<int, std::string> > m_ruleRemoveTargetById;
std::list< std::pair<std::pair<int, int>, std::string> > m_ruleRemoveTargetByIdRange;
/**
*

View File

@ -39,12 +39,36 @@ bool RuleRemoveTargetById::init(std::string *error) {
return false;
}
try {
m_id = std::stoi(param[0]);
} catch(...) {
error->assign("Not able to convert '" + param[0] +
"' into a number");
return false;
size_t dash = param[0].find('-');
if (dash != std::string::npos) {
std::string n1s = std::string(param[0], 0, dash);
std::string n2s = std::string(param[0], dash + 1, param[0].size() - (dash + 1));
int n1n = 0;
int n2n = 0;
try {
n1n = std::stoi(n1s);
} catch(...) {
error->assign("Not a number: " + n1s);
return false;
}
try {
n2n = std::stoi(n2s);
} catch(...) {
error->assign("Not a number: " + n2s);
return false;
}
if (n1n > n2n) {
error->assign("Invalid range: " + param[0]);
}
m_id = n1n;
m_id_end_of_range = n2n;
} else {
try {
m_id = std::stoi(param[0]);
} catch(...) {
error->assign("Not able to convert '" + param[0] + "' into a number");
return false;
}
}
m_target = param[1];
@ -54,8 +78,12 @@ bool RuleRemoveTargetById::init(std::string *error) {
bool RuleRemoveTargetById::execute(Transaction *transaction) const noexcept {
transaction->m_ruleRemoveTargetById.push_back(
std::make_pair(m_id, m_target));
if (m_id_end_of_range == 0) {
transaction->m_ruleRemoveTargetById.push_back(std::make_pair(m_id, m_target));
} else {
std::pair<int, int> id_range = std::make_pair(m_id, m_id_end_of_range);
transaction->m_ruleRemoveTargetByIdRange.push_back(std::make_pair(id_range, m_target));
}
return true;
}

View File

@ -35,6 +35,7 @@ class RuleRemoveTargetById : public ActionWithExecution {
explicit RuleRemoveTargetById(const std::string &action)
: Action(action),
m_id(0),
m_id_end_of_range(0),
m_target("")
{ }
@ -44,6 +45,7 @@ class RuleRemoveTargetById : public ActionWithExecution {
private:
int m_id;
int m_id_end_of_range;
std::string m_target;
};

View File

@ -194,6 +194,14 @@ inline void RuleWithOperator::getFinalVars(variables::Variables *vars,
}) != trans->m_ruleRemoveTargetById.end()) {
continue;
}
if (std::find_if(trans->m_ruleRemoveTargetByIdRange.begin(),
trans->m_ruleRemoveTargetByIdRange.end(),
[&, variable, this](std::pair<std::pair<int, int>, std::string> &m) -> bool {
return (m.first.first <= getId() && m.first.second >= getId()
&& m.second == *variable->getVariableKeyWithCollection());
}) != trans->m_ruleRemoveTargetByIdRange.end()) {
continue;
}
if (std::find_if(trans->m_ruleRemoveTargetByTag.begin(),
trans->m_ruleRemoveTargetByTag.end(),
[&, variable, trans, this](
@ -289,6 +297,17 @@ bool RuleWithOperator::evaluate(Transaction *trans) const {
continue;
}
if (exclusion.contains(v) ||
std::find_if(trans->m_ruleRemoveTargetByIdRange.begin(),
trans->m_ruleRemoveTargetByIdRange.end(),
[&, v, this](std::pair<std::pair<int, int>, std::string> &m) -> bool {
return (m.first.first <= getId() && m.first.second >= getId()
&& m.second == v->getName());
}) != trans->m_ruleRemoveTargetByIdRange.end()
) {
continue;
}
if (exclusion.contains(v) ||
std::find_if(trans->m_ruleRemoveTargetByTag.begin(),
trans->m_ruleRemoveTargetByTag.end(),

View File

@ -95,5 +95,170 @@
"SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:9002100,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=1;ARGS\"",
"SecRule ARGS \"@contains lhebs\" \"id:1,phase:3,t:none,status:202,block,deny,tag:'CRS'\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing CtlRuleRemoveTargetById (4) range: within range",
"expected":{
"http_code": 200
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120",
"Content-Type": "text/xml"
},
"uri":"/wp-login.php?whee&pwd=lhebs",
"method":"GET",
"body": [ ]
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:1,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=4-6;ARGS:pwd\"",
"SecRule ARGS \"@contains lhebs\" \"id:5,phase:2,t:none,deny,status:403\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing CtlRuleRemoveTargetById (5) range: within range but !target",
"expected":{
"http_code": 403
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120",
"Content-Type": "text/xml"
},
"uri":"/wp-login.php?whee&pswd=lhebs",
"method":"GET",
"body": [ ]
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:1,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=4-6;ARGS:pwd\"",
"SecRule ARGS \"@contains lhebs\" \"id:5,phase:2,t:none,deny,status:403\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing CtlRuleRemoveTargetById (6) range: outside of range",
"expected":{
"http_code": 403
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120",
"Content-Type": "text/xml"
},
"uri":"/wp-login.php?whee&pwd=lhebs",
"method":"GET",
"body": [ ]
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:1,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=4-6;ARGS:pwd\"",
"SecRule ARGS \"@contains lhebs\" \"id:7,phase:2,t:none,deny,status:403\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing CtlRuleRemoveTargetById (7) range: remove the collection",
"expected":{
"http_code": 200
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120",
"Content-Type": "text/xml"
},
"uri":"/wp-login.php?whee&pwd=lhebs",
"method":"GET",
"body": [ ]
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:1,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=4-6;ARGS\"",
"SecRule ARGS_NAMES|ARGS \"@contains lhebs\" \"id:5,phase:2,t:none,deny,status:403\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing CtlRuleRemoveTargetById (8) range: remove other collection",
"expected":{
"http_code": 403
},
"client":{
"ip":"200.249.12.31",
"port":123
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Cookie": "PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120",
"Content-Type": "text/xml"
},
"uri":"/wp-login.php?whee&pwd=lhebs",
"method":"GET",
"body": [ ]
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"rules":[
"SecRuleEngine On",
"SecRule REQUEST_FILENAME \"@endsWith /wp-login.php\" \"id:1,phase:2,t:none,nolog,pass,ctl:ruleRemoveTargetById=4-6;ARGS_NAMES\"",
"SecRule ARGS_NAMES|ARGS \"@contains lhebs\" \"id:5,phase:2,t:none,deny,status:403\""
]
}
]