Skip to content
This repository was archived by the owner on Jun 25, 2025. It is now read-only.

Commit 8d5df80

Browse files
Hamza ZerhouniChive
authored andcommitted
Adds support to multiple ranges in ctl:ruleRemoveTargetById (owasp-modsecurity#2110)
1 parent 6624a18 commit 8d5df80

File tree

7 files changed

+116
-19
lines changed

7 files changed

+116
-19
lines changed

CHANGES

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,16 @@ v3.0.4 - YYYY-MMM-DD (to be released)
3030
[@rdiperri-yottaa, @danbiagini-work, @mmelo-yottaa, @zimmerle]
3131
- Missing throw in Operator::instantiate
3232
[Issue #2106 - @marduone]
33+
- Adds support to multiple ranges in ctl:ruleRemoveTargetById
34+
[Issue #2110 - @theMiddleBlue, @zimmerle]
3335
- Making block action execution dependent of the SecEngine status
3436
[Issue #2113, #2111 - @theMiddleBlue, @airween]
3537
- Making block action execution dependent of the SecEngine status
3638
[Issue #1960 - @theMiddleBlue, @zimmerle, @airween, @victorhora]
3739
- Having body limits to respect the rule engine state
3840
[@zimmerle]
3941
- Fix SecRuleUpdateTargetById does not match regular expressions
40-
[Issue #1872 - @zimmerle, @anush-cr, @victorhora, @j0k2r]
42+
[Issue #1872 - @zimmerle, @anush-cr, @victorhora, @j0k2r]
4143
- Adds missing check for runtime ctl:ruleRemoveByTag
4244
[Issue #2102, #2099 - @airween]
4345
- Adds a new operator verifySVNR that checks for Austrian social
@@ -98,7 +100,7 @@ v3.0.4 - YYYY-MMM-DD (to be released)
98100
- Adds support to multiple ranges in ctl:ruleRemoveById
99101
[Issue #1956 - @theseion, @victorhora, @zimmerle]
100102
- Rule variable interpolation broken
101-
[Issue #1961 - @soonum, @zimmerle]
103+
[Issue #1961 - @soonum, @zimmerle]
102104
- Make the boundary check less strict as per RFC2046
103105
[Issue #1943 - @victorhora, @allanbomsft]
104106
- Fix buffer size for utf8toUnicode transformation
@@ -239,7 +241,7 @@ v3.0.3 - 2018-Nov-05
239241
[Issue #1739 - @p0pr0ck5]
240242
- Fix utils::string::ssplit() to handle delimiter in the end of string
241243
[Issue #1743, #1744 - @defanator]
242-
- Fix variable FILES_TMPNAMES
244+
- Fix variable FILES_TMPNAMES
243245
[Issue #1646, #1610 - @victorhora, @zimmerle, @defanator]
244246
- Fix memory leak in Collections
245247
[Issue #1729, #1730 - @defanator]
@@ -341,7 +343,7 @@ v3.0.0 - 2017-Dec-13
341343
- Adds support to WEBAPPID variable.
342344
[Issue #1027 - @zimmerle, @victorhora]
343345
- Adds support for SecWebAppId.
344-
[Issue #1442 - @zimmerle, @victorhora]
346+
[Issue #1442 - @zimmerle, @victorhora]
345347
- Adds support for SecRuleRemoveByTag.
346348
[Issue #1476 - @zimmerle, @victorhora]
347349
- Adds support for update target by message.
@@ -404,4 +406,3 @@ v3.0.0-rc1 - 2017-Aug-28
404406
------------------------
405407

406408
Very first public version.
407-

Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ TESTS+=test/test-cases/regression/config-update-target-by-tag.json
134134
TESTS+=test/test-cases/regression/config-xml_external_entity.json
135135
TESTS+=test/test-cases/regression/debug_log.json
136136
TESTS+=test/test-cases/regression/directive-sec_rule_script.json
137+
TESTS+=test/test-cases/regression/issue-2110.json
137138
TESTS+=test/test-cases/regression/issue-1152.json
138139
TESTS+=test/test-cases/regression/issue-1528.json
139140
TESTS+=test/test-cases/regression/issue-1565.json

headers/modsecurity/transaction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,7 @@ class Transaction : public TransactionAnchoredVariables {
477477
*
478478
*/
479479
std::list< std::pair<int, std::string> > m_ruleRemoveTargetById;
480+
std::list< std::pair<std::pair<int, int>, std::string> > m_ruleRemoveTargetByIdRange;
480481

481482
/**
482483
*

src/actions/ctl/rule_remove_target_by_id.cc

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,73 @@ bool RuleRemoveTargetById::init(std::string *error) {
3333
std::string what(m_parser_payload, 21, m_parser_payload.size() - 21);
3434
std::vector<std::string> param = utils::string::split(what, ';');
3535

36+
bool added = false;
37+
3638
if (param.size() < 2) {
3739
error->assign(what + " is not a valid `ID;VARIABLE'");
3840
return false;
3941
}
4042

41-
try {
42-
m_id = std::stoi(param[0]);
43-
} catch(...) {
44-
error->assign("Not able to convert '" + param[0] +
45-
"' into a number");
46-
return false;
43+
size_t dash = param[0].find('-');
44+
if (dash != std::string::npos) {
45+
std::string n1s = std::string(param[0], 0, dash);
46+
std::string n2s = std::string(param[0], dash + 1, param[0].size() - (dash + 1));
47+
int n1n = 0;
48+
int n2n = 0;
49+
try {
50+
n1n = std::stoi(n1s);
51+
added = true;
52+
} catch (...) {
53+
error->assign("Not a number: " + n1s);
54+
return false;
55+
}
56+
try {
57+
n2n = std::stoi(n2s);
58+
added = true;
59+
} catch (...) {
60+
error->assign("Not a number: " + n2s);
61+
return false;
62+
}
63+
64+
if (n1n > n2n) {
65+
error->assign("Invalid range: " + param[0]);
66+
return false;
67+
}
68+
m_ranges.push_back(std::make_pair(n1n, n2n));
69+
added = true;
70+
} else {
71+
try {
72+
int num = std::stoi(param[0]);
73+
m_ids.push_back(num);
74+
added = true;
75+
} catch (...) {
76+
error->assign("Not able to convert '" + param[0] +
77+
"' into a number");
78+
return false;
79+
}
4780
}
4881

49-
m_target = param[1];
82+
if (added) {
83+
m_target = param[1];
84+
return true;
85+
}
5086

51-
return true;
87+
error->assign("Not a number or range: " + what);
88+
return false;
5289
}
5390

5491
bool RuleRemoveTargetById::evaluate(Rule *rule, Transaction *transaction) {
92+
for (auto &i : m_ids) {
5593
transaction->m_ruleRemoveTargetById.push_back(
56-
std::make_pair(m_id, m_target));
57-
return true;
94+
std::make_pair(i, m_target));
95+
}
96+
97+
for (auto &i : m_ranges) {
98+
transaction->m_ruleRemoveTargetByIdRange.push_back(
99+
std::make_pair(i, m_target));
100+
}
101+
102+
return true;
58103
}
59104

60105

src/actions/ctl/rule_remove_target_by_id.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,13 @@ namespace ctl {
3030
class RuleRemoveTargetById : public Action {
3131
public:
3232
explicit RuleRemoveTargetById(std::string action)
33-
: Action(action, RunTimeOnlyIfMatchKind),
34-
m_id(0),
35-
m_target("") { }
33+
: Action(action, RunTimeOnlyIfMatchKind) { }
3634

3735
bool init(std::string *error) override;
3836
bool evaluate(Rule *rule, Transaction *transaction) override;
3937

40-
int m_id;
38+
std::list<std::pair<int, int> > m_ranges;
39+
std::list<int> m_ids;
4140
std::string m_target;
4241
};
4342

src/rule.cc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,23 @@ bool Rule::evaluate(Transaction *trans,
710710
v = NULL;
711711
continue;
712712
}
713+
714+
if (exclusion.contains(v->getKey()) ||
715+
std::find_if(trans->m_ruleRemoveTargetByIdRange.begin(),
716+
trans->m_ruleRemoveTargetByIdRange.end(),
717+
[&, v, this](std::pair<std::pair<int, int>, std::string> &m) -> bool {
718+
if (m.first.first <= m_ruleId && m.first.second >= m_ruleId) {
719+
return m.second == v->getKey();
720+
}
721+
722+
return false;
723+
}) != trans->m_ruleRemoveTargetByIdRange.end()
724+
) {
725+
delete v;
726+
v = NULL;
727+
continue;
728+
}
729+
713730
if (exclusion.contains(v->getKey()) ||
714731
std::find_if(trans->m_ruleRemoveTargetByTag.begin(),
715732
trans->m_ruleRemoveTargetByTag.end(),
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
[
2+
{
3+
"enabled":1,
4+
"version_min":300000,
5+
"title":"Testing ctl:ruleRemoveTargetById - issue 1444",
6+
"expected":{
7+
"http_code":200
8+
},
9+
"client":{
10+
"ip":"127.0.0.1",
11+
"port":123
12+
},
13+
"request":{
14+
"headers":{
15+
"Host":"localhost",
16+
"User-Agent":"curl/7.38.0",
17+
"Accept":"*/*"
18+
},
19+
"uri":"index.php?foo=bar&z=xxx",
20+
"method":"GET",
21+
"body": ""
22+
},
23+
"server":{
24+
"ip":"127.0.0.1",
25+
"port":80
26+
},
27+
"rules":[
28+
"SecRuleEngine On",
29+
"SecRule ARGS:foo \"@rx ^bar$\" \"id:100,phase:1,ctl:ruleRemoveTargetById=1000-1999;ARGS:z\"",
30+
"SecRule ARGS:z \"@rx ^xxx$\" \"id:1010,phase:1,deny,status:403\""
31+
]
32+
}
33+
]

0 commit comments

Comments
 (0)