Skip to content

Commit b6e629f

Browse files
Easton97-Jensjens
authored andcommitted
Fix Windows test include path and case-insensitive override matching
1 parent 633f2eb commit b6e629f

12 files changed

Lines changed: 196 additions & 10 deletions

File tree

build/win32/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ project(libModSecurityTests)
164164

165165
function(setTestTargetProperties executable)
166166
target_compile_definitions(${executable} PRIVATE WITH_PCRE2)
167-
target_include_directories(${executable} PRIVATE ${BASE_DIR} ${BASE_DIR}/headers)
167+
target_include_directories(${executable} PRIVATE ${BASE_DIR} ${BASE_DIR}/headers ${BASE_DIR}/others)
168168
target_link_libraries(${executable} PRIVATE libModSecurity pcre2::pcre2 dirent::dirent)
169169
add_package_dependency(${executable} WITH_YAJL yajl::yajl HAVE_YAJL)
170170
endfunction()
@@ -239,7 +239,7 @@ setTestTargetProperties(rules_optimization)
239239
project(libModSecurityExamples)
240240

241241
function(setExampleTargetProperties executable)
242-
target_include_directories(${executable} PRIVATE ${BASE_DIR} ${BASE_DIR}/headers)
242+
target_include_directories(${executable} PRIVATE ${BASE_DIR} ${BASE_DIR}/headers ${BASE_DIR}/others)
243243
target_link_libraries(${executable} PRIVATE libModSecurity)
244244
endfunction()
245245

src/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ OPERATORS = \
187187
operators/contains_word.cc \
188188
operators/detect_sqli.cc \
189189
operators/detect_xss.cc \
190+
operators/libinjection_adapter.cc \
190191
operators/ends_with.cc \
191192
operators/eq.cc \
192193
operators/fuzzy_hash.cc \

src/operators/detect_sqli.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
#include "src/operators/operator.h"
2323
#include "src/operators/libinjection_utils.h"
24-
#include "libinjection/src/libinjection.h"
24+
#include "src/operators/libinjection_adapter.h"
2525
#include "libinjection/src/libinjection_error.h"
2626

2727
namespace modsecurity::operators {
@@ -32,7 +32,7 @@ bool DetectSQLi::evaluate(Transaction *t, RuleWithActions *rule,
3232
std::array<char, 8> fingerprint{};
3333

3434
const injection_result_t sqli_result =
35-
libinjection_sqli(input.c_str(), input.length(), fingerprint.data());
35+
runLibinjectionSQLi(input.c_str(), input.length(), fingerprint.data());
3636

3737
if (t == nullptr) {
3838
return isMaliciousLibinjectionResult(sqli_result);
@@ -71,6 +71,9 @@ bool DetectSQLi::evaluate(Transaction *t, RuleWithActions *rule,
7171
std::string("Added DetectSQLi error input TX.0: ")
7272
+ input);
7373
}
74+
75+
// Keep m_matched untouched for parser-error paths to avoid
76+
// introducing synthetic fingerprints for non-TRUE results.
7477
break;
7578

7679
case LIBINJECTION_RESULT_FALSE:

src/operators/detect_xss.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
#include "src/operators/operator.h"
2121
#include "src/operators/libinjection_utils.h"
22-
#include "libinjection/src/libinjection.h"
22+
#include "src/operators/libinjection_adapter.h"
2323
#include "libinjection/src/libinjection_error.h"
2424

2525
namespace modsecurity::operators {
@@ -28,7 +28,7 @@ bool DetectXSS::evaluate(Transaction *t, RuleWithActions *rule,
2828
const std::string& input, RuleMessage &ruleMessage) {
2929

3030
const injection_result_t xss_result =
31-
libinjection_xss(input.c_str(), input.length());
31+
runLibinjectionXSS(input.c_str(), input.length());
3232

3333
if (t == nullptr) {
3434
return isMaliciousLibinjectionResult(xss_result);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* ModSecurity, http://www.modsecurity.org/
3+
*/
4+
5+
#include "src/operators/libinjection_adapter.h"
6+
7+
#include "libinjection/src/libinjection.h"
8+
9+
namespace modsecurity::operators {
10+
namespace {
11+
// Per-thread overrides avoid cross-thread interference during mtstress tests.
12+
thread_local DetectSQLiFn g_sqli_override = nullptr;
13+
thread_local DetectXSSFn g_xss_override = nullptr;
14+
}
15+
16+
injection_result_t runLibinjectionSQLi(const char *input, size_t len,
17+
char *fingerprint) {
18+
if (DetectSQLiFn fn = g_sqli_override) {
19+
return fn(input, len, fingerprint);
20+
}
21+
22+
return libinjection_sqli(input, len, fingerprint);
23+
}
24+
25+
injection_result_t runLibinjectionXSS(const char *input, size_t len) {
26+
if (DetectXSSFn fn = g_xss_override) {
27+
return fn(input, len);
28+
}
29+
30+
return libinjection_xss(input, len);
31+
}
32+
33+
void setLibinjectionSQLiOverrideForTesting(DetectSQLiFn fn) {
34+
g_sqli_override = fn;
35+
}
36+
37+
void setLibinjectionXSSOverrideForTesting(DetectXSSFn fn) {
38+
g_xss_override = fn;
39+
}
40+
41+
void clearLibinjectionOverridesForTesting() {
42+
g_sqli_override = nullptr;
43+
g_xss_override = nullptr;
44+
}
45+
46+
} // namespace modsecurity::operators
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* ModSecurity, http://www.modsecurity.org/
3+
*/
4+
5+
#ifndef SRC_OPERATORS_LIBINJECTION_ADAPTER_H_
6+
#define SRC_OPERATORS_LIBINJECTION_ADAPTER_H_
7+
8+
#include <cstddef>
9+
10+
#include "libinjection/src/libinjection_error.h" // matches detect_xss.cc, detect_sqli.cc, and libinjection_utils.h
11+
12+
namespace modsecurity::operators {
13+
14+
using DetectSQLiFn = injection_result_t (*)(const char *, size_t, char *);
15+
using DetectXSSFn = injection_result_t (*)(const char *, size_t);
16+
17+
injection_result_t runLibinjectionSQLi(const char *input, size_t len,
18+
char *fingerprint);
19+
injection_result_t runLibinjectionXSS(const char *input, size_t len);
20+
21+
void setLibinjectionSQLiOverrideForTesting(DetectSQLiFn fn);
22+
void setLibinjectionXSSOverrideForTesting(DetectXSSFn fn);
23+
void clearLibinjectionOverridesForTesting();
24+
25+
} // namespace modsecurity::operators
26+
27+
#endif // SRC_OPERATORS_LIBINJECTION_ADAPTER_H_

test/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ unit_tests_LDFLAGS = \
7373
unit_tests_CPPFLAGS = \
7474
-Icommon \
7575
-I$(top_srcdir)/ \
76+
-I$(top_srcdir)/others \
7677
-g \
7778
-I$(top_builddir)/headers \
7879
$(CURL_CFLAGS) \
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
[
2+
{
3+
"type": "op",
4+
"name": "detectXSS",
5+
"param": "",
6+
"input": "<div<div>",
7+
"ret": 1,
8+
"capture": 1,
9+
"libinjection_override": "error",
10+
"output": "<div<div>"
11+
},
12+
{
13+
"type": "op",
14+
"name": "detectSQLi",
15+
"param": "",
16+
"input": "''''''",
17+
"ret": 1,
18+
"capture": 1,
19+
"libinjection_override": "error",
20+
"output": "''''''"
21+
},
22+
{
23+
"type": "op",
24+
"name": "detectXSS",
25+
"param": "",
26+
"input": "<script>alert(1)</script>",
27+
"ret": 1,
28+
"capture": 1,
29+
"output": "<script>alert(1)</script>"
30+
},
31+
{
32+
"type": "op",
33+
"name": "detectSQLi",
34+
"param": "",
35+
"input": "ascii(substring(version() from 1 for 1))",
36+
"ret": 1,
37+
"capture": 1,
38+
"output": "f(f(f"
39+
}
40+
]

test/test-suite.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ TESTS+=test/test-cases/secrules-language-tests/operators/contains.json
198198
TESTS+=test/test-cases/secrules-language-tests/operators/containsWord.json
199199
TESTS+=test/test-cases/secrules-language-tests/operators/detectSQLi.json
200200
TESTS+=test/test-cases/secrules-language-tests/operators/detectXSS.json
201+
TESTS+=test/test-cases/unit/operator-libinjection-error.json
201202
TESTS+=test/test-cases/secrules-language-tests/operators/endsWith.json
202203
TESTS+=test/test-cases/secrules-language-tests/operators/eq.json
203204
TESTS+=test/test-cases/secrules-language-tests/operators/ge.json

test/unit/unit.cc

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#include "src/actions/transformations/transformation.h"
2929
#include "modsecurity/transaction.h"
3030
#include "modsecurity/actions/action.h"
31+
#include "src/actions/capture.h"
32+
#include "src/operators/libinjection_adapter.h"
3133

3234

3335
#include "test/common/modsecurity_test.h"
@@ -57,6 +59,34 @@ void print_help() {
5759
}
5860

5961

62+
namespace {
63+
injection_result_t sqli_force_error(const char *, size_t, char *) {
64+
return LIBINJECTION_RESULT_ERROR;
65+
}
66+
67+
injection_result_t xss_force_error(const char *, size_t) {
68+
return LIBINJECTION_RESULT_ERROR;
69+
}
70+
71+
void configure_libinjection_override(const UnitTest &t) {
72+
modsecurity::operators::clearLibinjectionOverridesForTesting();
73+
74+
if (t.libinjection_override != "error") {
75+
return;
76+
}
77+
78+
const std::string operator_name = modsecurity::utils::string::tolower(t.name);
79+
80+
if (operator_name == "detectsqli") {
81+
modsecurity::operators::setLibinjectionSQLiOverrideForTesting(
82+
sqli_force_error);
83+
} else if (operator_name == "detectxss") {
84+
modsecurity::operators::setLibinjectionXSSOverrideForTesting(
85+
xss_force_error);
86+
}
87+
}
88+
} // namespace
89+
6090
struct OperatorTest {
6191
using ItemType = Operator;
6292

@@ -71,13 +101,42 @@ struct OperatorTest {
71101
}
72102

73103
static UnitTestResult eval(ItemType &op, const UnitTest &t, modsecurity::Transaction &transaction) {
74-
modsecurity::RuleWithActions rule{nullptr, nullptr, "dummy.conf", -1};
104+
configure_libinjection_override(t);
105+
106+
std::unique_ptr<modsecurity::Actions> actions;
107+
if (t.capture) {
108+
actions = std::make_unique<modsecurity::Actions>();
109+
actions->push_back(new modsecurity::actions::Capture("capture"));
110+
}
111+
112+
modsecurity::RuleWithActions rule{actions.release(), nullptr, "dummy.conf", -1};
75113
modsecurity::RuleMessage ruleMessage{rule, transaction};
76-
return {op.evaluate(&transaction, &rule, t.input, ruleMessage), {}};
114+
115+
const bool matched = op.evaluate(&transaction, &rule, t.input, ruleMessage);
116+
117+
UnitTestResult result;
118+
result.ret = matched;
119+
if (t.capture) {
120+
auto tx0 = transaction.m_collections.m_tx_collection->resolveFirst("0");
121+
if (tx0 != nullptr) {
122+
result.output = *tx0;
123+
}
124+
}
125+
126+
modsecurity::operators::clearLibinjectionOverridesForTesting();
127+
return result;
77128
}
78129

79130
static bool check(const UnitTestResult &result, const UnitTest &t) {
80-
return result.ret != t.ret;
131+
if (result.ret != t.ret) {
132+
return true;
133+
}
134+
135+
if (t.capture || t.output.empty() == false) {
136+
return result.output != t.output;
137+
}
138+
139+
return false;
81140
}
82141
};
83142

0 commit comments

Comments
 (0)