Skip to content

Commit 759843d

Browse files
Merge branch 'v3/master' into v3/master-mbedtl-v4
2 parents 692c0cc + 1919573 commit 759843d

17 files changed

+1195
-74
lines changed

build/win32/CMakeLists.txt

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

187187
function(setTestTargetProperties executable)
188188
target_compile_definitions(${executable} PRIVATE WITH_PCRE2)
189-
target_include_directories(${executable} PRIVATE ${BASE_DIR} ${BASE_DIR}/headers)
189+
target_include_directories(${executable} PRIVATE ${BASE_DIR} ${BASE_DIR}/headers ${BASE_DIR}/others)
190190
target_link_libraries(${executable} PRIVATE libModSecurity pcre2::pcre2 dirent::dirent)
191191
add_package_dependency(${executable} WITH_YAJL yajl::yajl HAVE_YAJL)
192192
endfunction()
@@ -261,7 +261,7 @@ setTestTargetProperties(rules_optimization)
261261
project(libModSecurityExamples)
262262

263263
function(setExampleTargetProperties executable)
264-
target_include_directories(${executable} PRIVATE ${BASE_DIR} ${BASE_DIR}/headers)
264+
target_include_directories(${executable} PRIVATE ${BASE_DIR} ${BASE_DIR}/headers ${BASE_DIR}/others)
265265
target_link_libraries(${executable} PRIVATE libModSecurity)
266266
endfunction()
267267

others/Makefile.am

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ noinst_HEADERS = \
1515
libinjection/src/libinjection_sqli.h \
1616
libinjection/src/libinjection_sqli_data.h \
1717
libinjection/src/libinjection_xss.h \
18-
mbedtls/tf-psa-crypto/include/mbedtls/base64.h \
18+
libinjection/src/libinjection_error.h \
19+
mbedtls/include/mbedtls/base64.h \
20+
mbedtls/include/mbedtls/check_config.h \
1921
mbedtls/include/mbedtls/mbedtls_config.h \
2022
mbedtls/tf-psa-crypto/include/mbedtls/md.h \
2123
mbedtls/tf-psa-crypto/include/mbedtls/platform.h

others/libinjection

Submodule libinjection updated 155 files

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: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,45 +17,84 @@
1717

1818
#include <string>
1919
#include <list>
20+
#include <array>
2021

2122
#include "src/operators/operator.h"
22-
#include "libinjection/src/libinjection.h"
23-
24-
namespace modsecurity {
25-
namespace operators {
23+
#include "src/operators/libinjection_utils.h"
24+
#include "src/operators/libinjection_adapter.h"
25+
#include "src/utils/string.h"
26+
#include "libinjection/src/libinjection_error.h"
2627

28+
namespace modsecurity::operators {
2729

2830
bool DetectSQLi::evaluate(Transaction *t, RuleWithActions *rule,
2931
const std::string& input, RuleMessage &ruleMessage) {
30-
char fingerprint[8];
31-
int issqli;
32+
#ifndef NO_LOGS
33+
const std::string loggable_input =
34+
utils::string::limitTo(80, utils::string::toHexIfNeeded(input));
35+
#endif
36+
37+
std::array<char, 8> fingerprint{};
3238

33-
issqli = libinjection_sqli(input.c_str(), input.length(), fingerprint);
39+
const injection_result_t sqli_result =
40+
runLibinjectionSQLi(input.c_str(), input.length(), fingerprint.data());
3441

35-
if (!t) {
36-
goto tisempty;
42+
if (t == nullptr) {
43+
return isMaliciousLibinjectionResult(sqli_result);
3744
}
3845

39-
if (issqli) {
40-
t->m_matched.push_back(fingerprint);
41-
ms_dbg_a(t, 4, "detected SQLi using libinjection with " \
42-
"fingerprint '" + std::string(fingerprint) + "' at: '" +
43-
input + "'");
44-
if (rule && rule->hasCaptureAction()) {
45-
t->m_collections.m_tx_collection->storeOrUpdateFirst(
46-
"0", std::string(fingerprint));
47-
ms_dbg_a(t, 7, "Added DetectSQLi match TX.0: " + \
48-
std::string(fingerprint));
49-
}
50-
} else {
51-
ms_dbg_a(t, 9, "detected SQLi: not able to find an " \
52-
"inject on '" + input + "'");
46+
switch (sqli_result) {
47+
case LIBINJECTION_RESULT_TRUE:
48+
t->m_matched.emplace_back(fingerprint.data());
49+
50+
#ifndef NO_LOGS
51+
ms_dbg_a(t, 4,
52+
std::string("detected SQLi using libinjection with fingerprint '")
53+
+ fingerprint.data() + "' at: '" + loggable_input + "'");
54+
#endif
55+
56+
if (rule != nullptr && rule->hasCaptureAction()) {
57+
t->m_collections.m_tx_collection->storeOrUpdateFirst(
58+
"0", std::string(fingerprint.data()));
59+
60+
ms_dbg_a(t, 7,
61+
std::string("Added DetectSQLi match TX.0: ")
62+
+ fingerprint.data());
63+
}
64+
break;
65+
66+
case LIBINJECTION_RESULT_ERROR:
67+
#ifndef NO_LOGS
68+
ms_dbg_a(t, 4,
69+
std::string("libinjection parser error during SQLi analysis (")
70+
+ libinjectionResultToString(sqli_result)
71+
+ "); treating as match (fail-safe). Input: '"
72+
+ loggable_input + "'");
73+
#endif
74+
75+
if (rule != nullptr && rule->hasCaptureAction()) {
76+
t->m_collections.m_tx_collection->storeOrUpdateFirst(
77+
"0", input);
78+
79+
ms_dbg_a(t, 7,
80+
std::string("Added DetectSQLi error input TX.0: ")
81+
+ input);
82+
}
83+
84+
// Keep m_matched untouched for parser-error paths to avoid
85+
// introducing synthetic fingerprints for non-TRUE results.
86+
break;
87+
88+
case LIBINJECTION_RESULT_FALSE:
89+
#ifndef NO_LOGS
90+
ms_dbg_a(t, 9,
91+
std::string("libinjection was not able to find any SQLi in: ")
92+
+ loggable_input);
93+
#endif
94+
break;
5395
}
5496

55-
tisempty:
56-
return issqli != 0;
97+
return isMaliciousLibinjectionResult(sqli_result);
5798
}
5899

59-
60-
} // namespace operators
61-
} // namespace modsecurity
100+
} // namespace modsecurity::operators

src/operators/detect_xss.cc

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,36 +18,60 @@
1818
#include <string>
1919

2020
#include "src/operators/operator.h"
21-
#include "libinjection/src/libinjection.h"
22-
23-
24-
namespace modsecurity {
25-
namespace operators {
21+
#include "src/operators/libinjection_utils.h"
22+
#include "src/operators/libinjection_adapter.h"
23+
#include "src/utils/string.h"
24+
#include "libinjection/src/libinjection_error.h"
2625

26+
namespace modsecurity::operators {
2727

2828
bool DetectXSS::evaluate(Transaction *t, RuleWithActions *rule,
2929
const std::string& input, RuleMessage &ruleMessage) {
30-
int is_xss;
31-
32-
is_xss = libinjection_xss(input.c_str(), input.length());
33-
34-
if (t) {
35-
if (is_xss) {
36-
ms_dbg_a(t, 5, "detected XSS using libinjection.");
37-
if (rule && rule->hasCaptureAction()) {
38-
t->m_collections.m_tx_collection->storeOrUpdateFirst(
39-
"0", std::string(input));
40-
ms_dbg_a(t, 7, "Added DetectXSS match TX.0: " + \
41-
std::string(input));
30+
#ifndef NO_LOGS
31+
const std::string loggable_input =
32+
utils::string::limitTo(80, utils::string::toHexIfNeeded(input));
33+
#endif
34+
35+
const injection_result_t xss_result =
36+
runLibinjectionXSS(input.c_str(), input.length());
37+
38+
if (t == nullptr) {
39+
return isMaliciousLibinjectionResult(xss_result);
40+
}
41+
42+
switch (xss_result) {
43+
case LIBINJECTION_RESULT_TRUE:
44+
ms_dbg_a(t, 5, std::string("detected XSS using libinjection."));
45+
if (rule != nullptr && rule->hasCaptureAction()) {
46+
t->m_collections.m_tx_collection->storeOrUpdateFirst("0", input);
47+
ms_dbg_a(t, 7, std::string("Added DetectXSS match TX.0: ") + input);
4248
}
43-
} else {
44-
ms_dbg_a(t, 9, "libinjection was not able to " \
45-
"find any XSS in: " + input);
49+
break;
50+
51+
case LIBINJECTION_RESULT_ERROR:
52+
#ifndef NO_LOGS
53+
ms_dbg_a(t, 4,
54+
std::string("libinjection parser error during XSS analysis (")
55+
+ libinjectionResultToString(xss_result)
56+
+ "); treating as match (fail-safe). Input: "
57+
+ loggable_input);
58+
#endif
59+
if (rule != nullptr && rule->hasCaptureAction()) {
60+
t->m_collections.m_tx_collection->storeOrUpdateFirst("0", input);
61+
ms_dbg_a(t, 7, std::string("Added DetectXSS error input TX.0: ") + input);
4662
}
63+
break;
64+
65+
case LIBINJECTION_RESULT_FALSE:
66+
#ifndef NO_LOGS
67+
ms_dbg_a(t, 9,
68+
std::string("libinjection was not able to find any XSS in: ")
69+
+ loggable_input);
70+
#endif
71+
break;
4772
}
48-
return is_xss != 0;
49-
}
5073

74+
return isMaliciousLibinjectionResult(xss_result);
75+
}
5176

52-
} // namespace operators
53-
} // namespace modsecurity
77+
} // namespace modsecurity::operators
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* ModSecurity, http://www.modsecurity.org/
3+
* Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
4+
*
5+
* You may not use this file except in compliance with
6+
* the License. You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* If any of the files related to licensing are missing or if you have any
11+
* other questions related to licensing please contact Trustwave Holdings, Inc.
12+
* directly using the email address security@modsecurity.org.
13+
*
14+
*/
15+
16+
#include "src/operators/libinjection_adapter.h"
17+
18+
#include "libinjection/src/libinjection.h"
19+
20+
namespace modsecurity::operators {
21+
namespace {
22+
23+
// Per-thread overrides avoid cross-thread interference during mtstress tests.
24+
// Intentional design:
25+
// - thread_local to isolate tests across threads
26+
// - function pointers to keep zero-overhead call path
27+
// - mutable for test injection hooks
28+
// NOSONAR: required for testing override mechanism (see set*OverrideForTesting)
29+
thread_local DetectSQLiFn g_sqli_override = nullptr; // NOSONAR
30+
thread_local DetectXSSFn g_xss_override = nullptr; // NOSONAR
31+
32+
}
33+
34+
injection_result_t runLibinjectionSQLi(const char *input, size_t len,
35+
char *fingerprint) {
36+
if (DetectSQLiFn fn = g_sqli_override) {
37+
return fn(input, len, fingerprint);
38+
}
39+
40+
return libinjection_sqli(input, len, fingerprint);
41+
}
42+
43+
injection_result_t runLibinjectionXSS(const char *input, size_t len) {
44+
if (DetectXSSFn fn = g_xss_override) {
45+
return fn(input, len);
46+
}
47+
48+
return libinjection_xss(input, len);
49+
}
50+
51+
// Test-only hook: allows injecting alternative detection functions
52+
// NOSONAR: function pointer is intentional (no std::function overhead)
53+
void setLibinjectionSQLiOverrideForTesting(DetectSQLiFn fn) { // NOSONAR
54+
g_sqli_override = fn;
55+
}
56+
57+
// Test-only hook: allows injecting alternative detection functions
58+
// NOSONAR: function pointer is intentional (no std::function overhead)
59+
void setLibinjectionXSSOverrideForTesting(DetectXSSFn fn) { // NOSONAR
60+
g_xss_override = fn;
61+
}
62+
63+
void clearLibinjectionOverridesForTesting() {
64+
g_sqli_override = nullptr;
65+
g_xss_override = nullptr;
66+
}
67+
68+
} // namespace modsecurity::operators
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* ModSecurity, http://www.modsecurity.org/
3+
* Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
4+
*
5+
* You may not use this file except in compliance with
6+
* the License. You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* If any of the files related to licensing are missing or if you have any
11+
* other questions related to licensing please contact Trustwave Holdings, Inc.
12+
* directly using the email address security@modsecurity.org.
13+
*
14+
*/
15+
16+
#ifndef SRC_OPERATORS_LIBINJECTION_ADAPTER_H_
17+
#define SRC_OPERATORS_LIBINJECTION_ADAPTER_H_
18+
19+
#include <cstddef>
20+
21+
#include "libinjection/src/libinjection_error.h" // matches detect_xss.cc, detect_sqli.cc, and libinjection_utils.h
22+
23+
namespace modsecurity::operators {
24+
25+
using DetectSQLiFn = injection_result_t (*)(const char *, size_t, char *);
26+
using DetectXSSFn = injection_result_t (*)(const char *, size_t);
27+
28+
injection_result_t runLibinjectionSQLi(const char *input, size_t len,
29+
char *fingerprint);
30+
injection_result_t runLibinjectionXSS(const char *input, size_t len);
31+
32+
void setLibinjectionSQLiOverrideForTesting(DetectSQLiFn fn);
33+
void setLibinjectionXSSOverrideForTesting(DetectXSSFn fn);
34+
void clearLibinjectionOverridesForTesting();
35+
36+
} // namespace modsecurity::operators
37+
38+
#endif // SRC_OPERATORS_LIBINJECTION_ADAPTER_H_

src/operators/libinjection_utils.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* ModSecurity, http://www.modsecurity.org/
3+
* Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
4+
*
5+
* You may not use this file except in compliance with
6+
* the License. You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* If any of the files related to licensing are missing or if you have any
11+
* other questions related to licensing please contact Trustwave Holdings, Inc.
12+
* directly using the email address security@modsecurity.org.
13+
*
14+
*/
15+
16+
#ifndef SRC_OPERATORS_LIBINJECTION_UTILS_H_
17+
#define SRC_OPERATORS_LIBINJECTION_UTILS_H_
18+
19+
#include "libinjection/src/libinjection_error.h"
20+
21+
namespace modsecurity::operators {
22+
23+
/*
24+
* libinjection parser errors are handled in fail-safe mode as suspicious
25+
* results, so callers can block on both confirmed detections and parser
26+
* failures.
27+
*/
28+
static inline bool isMaliciousLibinjectionResult(injection_result_t result) {
29+
return result == LIBINJECTION_RESULT_TRUE
30+
|| result == LIBINJECTION_RESULT_ERROR;
31+
}
32+
33+
static inline const char *libinjectionResultToString(injection_result_t result) {
34+
switch (result) {
35+
case LIBINJECTION_RESULT_TRUE:
36+
return "attack-detected";
37+
case LIBINJECTION_RESULT_FALSE:
38+
return "no-attack";
39+
case LIBINJECTION_RESULT_ERROR:
40+
return "parser-error";
41+
}
42+
43+
return "unexpected-result";
44+
}
45+
46+
} // namespace modsecurity::operators
47+
48+
#endif // SRC_OPERATORS_LIBINJECTION_UTILS_H_

0 commit comments

Comments
 (0)