Skip to content

Commit ce3abf2

Browse files
author
Felipe Zimmerle
committed
Adds support to multiple ranges in ctl:ruleRemoveById
Issue #1956
1 parent e712d30 commit ce3abf2

File tree

7 files changed

+265
-11
lines changed

7 files changed

+265
-11
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
v3.0.4 - YYYY-MMM-DD (to be released)
22
-------------------------------------
33

4+
- Adds support to multiple ranges in ctl:ruleRemoveById
5+
[Issue #1956 - @theseion, @victorhora, @zimmerle]
46
- Rule variable interpolation broken
57
[Issue #1961 - @soonum, @zimmerle]
68
- Make the boundary check less strict as per RFC2046

Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ TESTS+=test/test-cases/regression/issue-1850.json
9595
TESTS+=test/test-cases/regression/issue-1725.json
9696
TESTS+=test/test-cases/regression/issue-1941.json
9797
TESTS+=test/test-cases/regression/issue-1943.json
98+
TESTS+=test/test-cases/regression/issue-1956.json
9899
TESTS+=test/test-cases/regression/variable-RESPONSE_HEADERS.json
99100
TESTS+=test/test-cases/regression/config-include.json
100101
TESTS+=test/test-cases/regression/variable-WEBSERVER_ERROR_LOG.json

headers/modsecurity/transaction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ class Transaction : public TransactionAnchoredVariables {
461461
*
462462
*/
463463
std::list<int > m_ruleRemoveById;
464+
std::list<std::pair<int, int> > m_ruleRemoveByIdRange;
464465

465466
/**
466467
*

src/actions/ctl/rule_remove_by_id.cc

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <string>
2020

2121
#include "modsecurity/transaction.h"
22+
#include "src/utils/string.h"
2223

2324
namespace modsecurity {
2425
namespace actions {
@@ -27,20 +28,69 @@ namespace ctl {
2728

2829
bool RuleRemoveById::init(std::string *error) {
2930
std::string what(m_parser_payload, 15, m_parser_payload.size() - 15);
31+
bool added = false;
32+
std::vector<std::string> toRemove = utils::string::ssplit(what, ' ');
33+
for (std::string &a : toRemove) {
34+
std::string b = modsecurity::utils::string::parserSanitizer(a);
35+
if (b.size() == 0) {
36+
continue;
37+
}
3038

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

39-
return true;
78+
if (added) {
79+
return true;
80+
}
81+
82+
error->assign("Not a number or range: " + what);
83+
return false;
4084
}
4185

4286
bool RuleRemoveById::evaluate(Rule *rule, Transaction *transaction) {
43-
transaction->m_ruleRemoveById.push_back(m_id);
87+
for (auto &i : m_ids) {
88+
transaction->m_ruleRemoveById.push_back(i);
89+
}
90+
for (auto &i : m_ranges) {
91+
transaction->m_ruleRemoveByIdRange.push_back(i);
92+
}
93+
4494
return true;
4595
}
4696

src/actions/ctl/rule_remove_by_id.h

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

3635
bool init(std::string *error) override;
3736
bool evaluate(Rule *rule, Transaction *transaction) override;
3837

39-
int m_id;
38+
std::list<std::pair<int, int> > m_ranges;
39+
std::list<int> m_ids;
4040
};
4141

4242

src/rule.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,14 @@ bool Rule::evaluate(Transaction *trans,
656656
" was skipped due to a ruleRemoveById action...");
657657
return true;
658658
}
659+
for (auto &i : trans->m_ruleRemoveByIdRange) {
660+
if (!(i.first <= m_ruleId && i.second >= m_ruleId)) {
661+
continue;
662+
}
663+
ms_dbg_a(trans, 9, "Rule id: " + std::to_string(m_ruleId) +
664+
" was skipped due to a ruleRemoveById action...");
665+
return true;
666+
}
659667

660668
if (m_op->m_string) {
661669
eparam = m_op->m_string->evaluate(trans);
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
[
2+
{
3+
"enabled": 1,
4+
"version_min": 209000,
5+
"version_max": -1,
6+
"title": "ctl:ruleRemoveById doesn't handle all ranges equally 1",
7+
"url": "https:\/\/github.com\/SpiderLabs\/ModSecurity\/issues\/1956",
8+
"gihub_issue": 1956,
9+
"client": {
10+
"ip": "200.249.12.31",
11+
"port": 2313
12+
},
13+
"server": {
14+
"ip": "200.249.12.31",
15+
"port": 80
16+
},
17+
"request": {
18+
"headers": {
19+
"Host": "www.google.com"
20+
},
21+
"uri": "\/test.pl?param1= test &param2=<a href=\"javascript:alert(1)\">)",
22+
"body": "",
23+
"method": "GET",
24+
"http_version": 1.1
25+
},
26+
"response": {
27+
"headers": "",
28+
"body": ""
29+
},
30+
"expected": {
31+
"audit_log": "",
32+
"debug_log": "Rule id: 913104 was skipped due to a ruleRemoveById",
33+
"error_log": ""
34+
},
35+
"rules": [
36+
"SecRule REQUEST_URI \"@beginsWith /test\" \"id:1001,phase:request,pass,nolog,t:none,ctl:ruleRemoveById=913103-913105\"",
37+
"SecRule REQUEST_URI \"@beginsWith /test\" \"id:913104,phase:request,pass,nolog,t:none,msg:'whee'\""
38+
]
39+
},
40+
{
41+
"enabled": 1,
42+
"version_min": 209000,
43+
"version_max": -1,
44+
"title": "ctl:ruleRemoveById doesn't handle all ranges equally 2",
45+
"url": "https:\/\/github.com\/SpiderLabs\/ModSecurity\/issues\/1956",
46+
"gihub_issue": 1956,
47+
"client": {
48+
"ip": "200.249.12.31",
49+
"port": 2313
50+
},
51+
"server": {
52+
"ip": "200.249.12.31",
53+
"port": 80
54+
},
55+
"request": {
56+
"headers": {
57+
"Host": "www.google.com"
58+
},
59+
"uri": "\/test.pl?param1= test &param2=<a href=\"javascript:alert(1)\">)",
60+
"body": "",
61+
"method": "GET",
62+
"http_version": 1.1
63+
},
64+
"response": {
65+
"headers": "",
66+
"body": ""
67+
},
68+
"expected": {
69+
"audit_log": "",
70+
"debug_log": "Rule id: 913104 was skipped due to a ruleRemoveById",
71+
"error_log": ""
72+
},
73+
"rules": [
74+
"SecRule REQUEST_URI \"@beginsWith /test\" \"id:1001,phase:request,pass,nolog,t:none,ctl:ruleRemoveById=913104\"",
75+
"SecRule REQUEST_URI \"@beginsWith /test\" \"id:913104,phase:request,pass,nolog,t:none,msg:'whee'\""
76+
]
77+
},
78+
{
79+
"enabled": 1,
80+
"version_min": 209000,
81+
"version_max": -1,
82+
"title": "ctl:ruleRemoveById doesn't handle all ranges equally 3",
83+
"url": "https:\/\/github.com\/SpiderLabs\/ModSecurity\/issues\/1956",
84+
"gihub_issue": 1956,
85+
"client": {
86+
"ip": "200.249.12.31",
87+
"port": 2313
88+
},
89+
"server": {
90+
"ip": "200.249.12.31",
91+
"port": 80
92+
},
93+
"request": {
94+
"headers": {
95+
"Host": "www.google.com"
96+
},
97+
"uri": "\/test.pl?param1= test &param2=<a href=\"javascript:alert(1)\">)",
98+
"body": "",
99+
"method": "GET",
100+
"http_version": 1.1
101+
},
102+
"response": {
103+
"headers": "",
104+
"body": ""
105+
},
106+
"expected": {
107+
"audit_log": "",
108+
"debug_log": "Rule id: 913103 was skipped due to a ruleRemoveById",
109+
"error_log": ""
110+
},
111+
"rules": [
112+
"SecRule REQUEST_URI \"@beginsWith /test\" \"id:1001,phase:request,pass,nolog,t:none,ctl:ruleRemoveById=913103-913105\"",
113+
"SecRule REQUEST_URI \"@beginsWith /test\" \"id:913103,phase:request,pass,nolog,t:none,msg:'whee'\""
114+
]
115+
},
116+
{
117+
"enabled": 1,
118+
"version_min": 209000,
119+
"version_max": -1,
120+
"title": "ctl:ruleRemoveById doesn't handle all ranges equally 4",
121+
"url": "https:\/\/github.com\/SpiderLabs\/ModSecurity\/issues\/1956",
122+
"gihub_issue": 1956,
123+
"client": {
124+
"ip": "200.249.12.31",
125+
"port": 2313
126+
},
127+
"server": {
128+
"ip": "200.249.12.31",
129+
"port": 80
130+
},
131+
"request": {
132+
"headers": {
133+
"Host": "www.google.com"
134+
},
135+
"uri": "\/test.pl?param1= test &param2=<a href=\"javascript:alert(1)\">)",
136+
"body": "",
137+
"method": "GET",
138+
"http_version": 1.1
139+
},
140+
"response": {
141+
"headers": "",
142+
"body": ""
143+
},
144+
"expected": {
145+
"audit_log": "",
146+
"debug_log": "Rule id: 913105 was skipped due to a ruleRemoveById",
147+
"error_log": ""
148+
},
149+
"rules": [
150+
"SecRule REQUEST_URI \"@beginsWith /test\" \"id:1001,phase:request,pass,nolog,t:none,ctl:ruleRemoveById=913103-913105\"",
151+
"SecRule REQUEST_URI \"@beginsWith /test\" \"id:913105,phase:request,pass,nolog,t:none,msg:'whee'\""
152+
]
153+
},
154+
{
155+
"enabled": 1,
156+
"version_min": 209000,
157+
"version_max": -1,
158+
"title": "ctl:ruleRemoveById doesn't handle all ranges equally 5",
159+
"url": "https:\/\/github.com\/SpiderLabs\/ModSecurity\/issues\/1956",
160+
"gihub_issue": 1956,
161+
"client": {
162+
"ip": "200.249.12.31",
163+
"port": 2313
164+
},
165+
"server": {
166+
"ip": "200.249.12.31",
167+
"port": 80
168+
},
169+
"request": {
170+
"headers": {
171+
"Host": "www.google.com"
172+
},
173+
"uri": "\/test.pl?param1= test &param2=<a href=\"javascript:alert(1)\">)",
174+
"body": "",
175+
"method": "GET",
176+
"http_version": 1.1
177+
},
178+
"response": {
179+
"headers": "",
180+
"body": ""
181+
},
182+
"expected": {
183+
"audit_log": "",
184+
"debug_log": "Rule: 913102. Executing operator",
185+
"error_log": ""
186+
},
187+
"rules": [
188+
"SecRule REQUEST_URI \"@beginsWith /test\" \"id:1001,phase:request,pass,nolog,t:none,ctl:ruleRemoveById=913103-913105\"",
189+
"SecRule REQUEST_URI \"@beginsWith /test\" \"id:913102,phase:request,pass,nolog,t:none,msg:'whee'\""
190+
]
191+
}
192+
]

0 commit comments

Comments
 (0)