Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ Windows build information can be found [here](build/win32/README.md).
* **Default:** PCRE2 is detected and used.
* **Fallback:** legacy PCRE can be used if `--with-pcre` is explicitly provided (`WITH_PCRE`).
* In other words, current builds expect PCRE2 unless explicitly configured otherwise.
* `@rx` and `@rxGlobal` compile patterns with `DOTALL | MULTILINE` by default: `DOTALL`
lets `.` match newlines, and `MULTILINE` lets `^`/`$` anchor at every internal line
break rather than only at the start/end of the whole subject. Pass
`--enable-regex-dollar-endonly=yes` to compile them with `DOTALL | DOLLAR_ENDONLY`
instead: without `MULTILINE`, `^`/`$` anchor only at the start/end of the whole
subject, and `DOLLAR_ENDONLY` further restricts `$` to match only there rather than
also just before a trailing newline. `DOTALL` is unchanged either way, so patterns
can still match across internal line breaks via `.`. This matches ModSecurity v2's
`@rx` behavior. The flag is disabled by default; see
[issue #3295](https://github.com/owasp-modsecurity/ModSecurity/issues/3295).

All other dependencies are related to operators specified within SecRules or configuration directives and may not be required for compilation.

Expand Down
5 changes: 5 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@ MSC_ARG_ENABLE_BOOL([afl-fuzz], [Turn on the afl fuzzer compilation utilities],
MSC_ARG_ENABLE_BOOL([examples], [Turn on the examples compilation (default option)], [true], [buildExamples])
MSC_ARG_ENABLE_BOOL([parser-generation], [Enables parser generation during the build], [false], [buildParser])
MSC_ARG_ENABLE_BOOL([mutex-on-pm], [Treat pm operations as critical section], [false], [mutexPm])
MSC_ARG_ENABLE_BOOL([regex-dollar-endonly], [Compile @rx/@rxGlobal patterns with PCRE(2)_DOLLAR_ENDONLY instead of PCRE(2)_MULTILINE, matching ModSecurity v2 behavior (see issue #3295)], [false], [regexDollarEndonly])
if test "$regexDollarEndonly" = "true"; then
MODSEC_REGEX_DOLLAR_ENDONLY_CPPFLAGS="-DMODSEC_REGEX_DOLLAR_ENDONLY=1"
GLOBAL_CPPFLAGS="$GLOBAL_CPPFLAGS $MODSEC_REGEX_DOLLAR_ENDONLY_CPPFLAGS"
fi


if test $buildParser = true; then
Expand Down
9 changes: 7 additions & 2 deletions src/operators/rx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,15 @@
namespace modsecurity {
namespace operators {

#ifdef MODSEC_REGEX_DOLLAR_ENDONLY
static const bool kRxMultiLine = false;
#else
static const bool kRxMultiLine = true;
#endif

bool Rx::init(const std::string &arg, std::string *error) {
if (m_string->m_containsMacro == false) {
m_re = new Regex(m_param);
m_re = new Regex(m_param, false, kRxMultiLine);
}

return true;
Expand All @@ -46,7 +51,7 @@ bool Rx::evaluate(Transaction *transaction, RuleWithActions *rule,

if (m_string->m_containsMacro) {
std::string eparam(m_string->evaluate(transaction));
re = new Regex(eparam);
re = new Regex(eparam, false, kRxMultiLine);
} else {
re = m_re;
}
Expand Down
9 changes: 7 additions & 2 deletions src/operators/rx_global.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,15 @@
namespace modsecurity {
namespace operators {

#ifdef MODSEC_REGEX_DOLLAR_ENDONLY
static const bool kRxGlobalMultiLine = false;
#else
static const bool kRxGlobalMultiLine = true;
#endif

bool RxGlobal::init(const std::string &arg, std::string *error) {
if (m_string->m_containsMacro == false) {
m_re = new Regex(m_param);
m_re = new Regex(m_param, false, kRxGlobalMultiLine);
}

return true;
Expand All @@ -46,7 +51,7 @@ bool RxGlobal::evaluate(Transaction *transaction, RuleWithActions *rule,

if (m_string->m_containsMacro) {
std::string eparam(m_string->evaluate(transaction));
re = new Regex(eparam);
re = new Regex(eparam, false, kRxGlobalMultiLine);
} else {
re = m_re;
}
Expand Down
7 changes: 4 additions & 3 deletions src/utils/regex.cc
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,12 @@ bool crlfIsNewline() {
return crlf_is_newline;
}

Regex::Regex(const std::string& pattern_, bool ignoreCase)
Regex::Regex(const std::string& pattern_, bool ignoreCase, bool multiLine)
: pattern(pattern_.empty() ? ".*" : pattern_) {
#ifndef WITH_PCRE
PCRE2_SPTR pcre2_pattern = reinterpret_cast<PCRE2_SPTR>(pattern.c_str());
uint32_t pcre2_options = (PCRE2_DOTALL|PCRE2_MULTILINE);
uint32_t pcre2_options = PCRE2_DOTALL |
(multiLine ? PCRE2_MULTILINE : PCRE2_DOLLAR_ENDONLY);
if (ignoreCase) {
pcre2_options |= PCRE2_CASELESS;
Comment thread
fzipi marked this conversation as resolved.
}
Expand All @@ -103,7 +104,7 @@ Regex::Regex(const std::string& pattern_, bool ignoreCase)
#else
const char *errptr = nullptr;
int erroffset;
int flags = (PCRE_DOTALL|PCRE_MULTILINE);
int flags = PCRE_DOTALL | (multiLine ? PCRE_MULTILINE : PCRE_DOLLAR_ENDONLY);

if (ignoreCase == true) {
flags |= PCRE_CASELESS;
Expand Down
3 changes: 2 additions & 1 deletion src/utils/regex.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ struct SMatchCapture {

class Regex {
public:
explicit Regex(const std::string& pattern_, bool ignoreCase = false);
explicit Regex(const std::string& pattern_, bool ignoreCase = false,
bool multiLine = true);
~Regex();

// m_pc and m_pce can't be easily copied
Expand Down
3 changes: 3 additions & 0 deletions test/regression/regression.cc
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,9 @@
#ifdef WITH_LIBXML2
resources.push_back("libxml2");
#endif
#ifdef MODSEC_REGEX_DOLLAR_ENDONLY
resources.push_back("regex-dollar-endonly");

Check warning on line 434 in test/regression/regression.cc

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of "push_back" with "emplace_back".

See more on https://sonarcloud.io/project/issues?id=owasp-modsecurity_ModSecurity&issues=AZ978PPJLJyjbmyN_kyM&open=AZ978PPJLJyjbmyN_kyM&pullRequest=3600
#endif

#ifdef NO_LOGS
std::cout << "Test utility cannot work without logging support." \
Expand Down
94 changes: 94 additions & 0 deletions test/test-cases/regression/operator-rx-dollar-endonly.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
[
{
"enabled": 1,
"version_min": 300000,
"resource": "regex-dollar-endonly",
"title": "Testing Operator :: @rx --enable-regex-dollar-endonly (single-line match still blocks)",
"client": {
"ip": "200.249.12.31",
"port": 123
},
"server": {
"ip": "200.249.12.31",
"port": 80
},
"request": {
"headers": {
"Host": "localhost",
"User-Agent": "curl/7.38.0",
"Accept": "*/*",
"Content-Length": "0"
},
"uri": "/?param1=hello%20world",
"method": "GET",
"body": [
""
]
},
"response": {
"headers": {
"Date": "Mon, 13 Jul 2015 20:02:41 GMT",
"Last-Modified": "Sun, 26 Oct 2014 22:33:37 GMT",
"Content-Type": "text/html",
"Content-Length": "8"
},
"body": [
"no need."
]
},
"expected": {
"debug_log": "Executing operator \"Rx\"",
"http_code": 403
},
"rules": [
"SecRuleEngine On",
"SecRule ARGS:param1 \"^hello.*world$\" \"id:1,phase:2,deny,log,msg:'multiline-anchor-test'\""
]
},
{
"enabled": 1,
"version_min": 300000,
"resource": "regex-dollar-endonly",
"title": "Testing Operator :: @rx --enable-regex-dollar-endonly (anchors do not span internal line breaks)",
"client": {
"ip": "200.249.12.31",
"port": 123
},
"server": {
"ip": "200.249.12.31",
"port": 80
},
"request": {
"headers": {
"Host": "localhost",
"User-Agent": "curl/7.38.0",
"Accept": "*/*",
"Content-Length": "0"
},
"uri": "/?param1=test%0Ahello%20world%0Amore",
"method": "GET",
"body": [
""
]
},
"response": {
"headers": {
"Date": "Mon, 13 Jul 2015 20:02:41 GMT",
"Last-Modified": "Sun, 26 Oct 2014 22:33:37 GMT",
"Content-Type": "text/html",
"Content-Length": "8"
},
"body": [
"no need."
]
},
"expected": {
"debug_log": "Executing operator \"Rx\"",
"http_code": 200
},
"rules": [
"SecRuleEngine On",
"SecRule ARGS:param1 \"^hello.*world$\" \"id:1,phase:2,deny,log,msg:'multiline-anchor-test'\""
]
}
]
1 change: 1 addition & 0 deletions test/test-suite.in
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ TESTS+=test/test-cases/regression/operator-ipMatchFromFile.json
TESTS+=test/test-cases/regression/operator-pm.json
TESTS+=test/test-cases/regression/operator-pmfromfile.json
TESTS+=test/test-cases/regression/operator-rx.json
TESTS+=test/test-cases/regression/operator-rx-dollar-endonly.json
TESTS+=test/test-cases/regression/operator-rxGlobal.json
TESTS+=test/test-cases/regression/operator-UnconditionalMatch.json
TESTS+=test/test-cases/regression/operator-validate-byte-range.json
Expand Down
Loading