mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Squashed 'src/deps/src/modsecurity/' changes from 205dac0e8..ccc2d9b53
ccc2d9b53 Change release version to v3.0.10 092921d87 Merge pull request #2934 from martinhsv/v3/master ab5658f2d Fix: worst-case time in implementation of four transformations 3f0971666 CHANGES entry for previous PR fea6e6d60 Merge pull request #2901 from airween/v3/pcrelimittx 2cb6344bf Merge pull request #2916 from martinhsv/v3/master f812a3d72 Make MULTIPART_PART_HEADERS accessible to lua 85c876077 Merge pull request #2915 from martinhsv/v3/master 63bbf624d Remove check-static from macos builds b8e1aedef Fix: Lua scripts cannot read whole collection at once b84f32d6f Merge pull request #2909 from martinhsv/v3/master 938707d11 Fix: quoted Include config with wildcard 4403a163c Set TX:MSC_PCRE_LIMITS_EXCEEDED variable is limits exceeded 2121938c5 Change some parms to reference-to-const to satisfy cppcheck da8782ce7 Minor whitespace adjustment fdeaf17c6 CHANGES entry for previous PR 1ca282a5e Add exclusions due to newer cppcheck version f8ec87337 github workflow: update macos version to macos-11 09a135baa Merge pull request #2736 from brandonpayton/add-regex-match-limits-and-error-reporting 62bbd7b07 Correction to previous cppcheck suppression adjustment 95c7009b8 Add cppcheck suppressions 1078a7cfa Change some parms from pass-by-value to reference-to-const 8d91a5084 github workflow: toggle pcre2 instead of ssdeep in Ubuntu tests 4fac8d72f Address some constParameter complaints from cppcheck e9277e199 CHANGES entry for previous PR 4050c840f Merge pull request #2868 from grnet/v3/fix-multimatch-chain 12add9aef Fix meta-actions not being applied if multiMatch is enabled in the chain starter rule 808148ce0 CHANGES entry and cppcheck suppression adjustment for prev PR 5b709d9da Merge pull request #2866 from grnet/v3/fix-multimatch-tags 7ca571952 CHANGES entry for previous PR 7cf0445ad Merge pull request #2870 from airween/v3/multipartpartheaderfix 6623c0ae2 Changed strip methodology to MULTIPART_PART_HEADERS 6fbdee9ff Merge branch 'v3/master' of https://github.com/SpiderLabs/ModSecurity into v3/multipartpartheaderfix a830ef634 Merge pull request #2894 from martinhsv/v3/master 8d62ac4b0 Configure: use AS_ECHO_N instead echo -n 6fc270e22 Merge pull request #2891 from martinhsv/v3/master b9eb39af8 Adjust position of memset from 2890 09568351d CHANGES entry for previous PR 5365a17c5 Merge pull request #2846 from tomsommer/patch-1 f8db5fc85 Remove no-longer-needed cppcheck suppressions a5320add2 Refactoring: remove two unneeded local vars from multipart parser 9ea50a497 Change arg from pass-by-value (satisify cppcheck) c34bd91a4 CHANGES: Preparing for next version d875738bd Add PCRE error tests for rx operator 6f1bd27fe Move var into conditional block where used 23a0e2617 Give PCRE error vars initial value f3d8198b8 Respond to code review feedback 0c42ee229 Switch to simpler PCRE error flags 8c4b7c18e Fix some style issues in regex util header 8c269d31c Update Regex util to support match limits 18adbb6fd Merge branch 'v3/master' of https://github.com/SpiderLabs/ModSecurity into v3/multipartpartheaderfix 0a296af37 Add regression test case 514abeb51 Remove EOL chars from MULTIPART_PART_HEADER variable d3a6b6a6f Fix tags not being populated in audit log when multiMatch is enabled 3caac9942 Also test empty lines git-subtree-dir: src/deps/src/modsecurity git-subtree-split: ccc2d9b53632fb5088673bbaafedf0d8d4b5f1d8
This commit is contained in:
parent
a75b90f525
commit
e0a89a2fcd
44 changed files with 8637 additions and 7832 deletions
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
- {label: "wo yajl", opt: "--without-yajl" }
|
||||
- {label: "wo geoip", opt: "--without-geoip" }
|
||||
- {label: "wo lmdb", opt: "--without-lmdb" }
|
||||
- {label: "wo ssdeep", opt: "--without-ssdeep" }
|
||||
- {label: "with pcre2", opt: "--with-pcre2" }
|
||||
- {label: "wo lua", opt: "--without-lua" }
|
||||
- {label: "without maxmind", opt: "--without-maxmind" }
|
||||
steps:
|
||||
|
|
@ -26,7 +26,7 @@ jobs:
|
|||
run: |
|
||||
sudo add-apt-repository --yes ppa:maxmind/ppa
|
||||
sudo apt-get update -y -qq
|
||||
sudo apt-get install -y libfuzzy-dev libyajl-dev libgeoip-dev liblua5.2-dev liblmdb-dev cppcheck libmaxminddb-dev libcurl4-openssl-dev
|
||||
sudo apt-get install -y libfuzzy-dev libyajl-dev libgeoip-dev liblua5.2-dev liblmdb-dev cppcheck libmaxminddb-dev libcurl4-openssl-dev libpcre2-dev pcre2-utils
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
|
|
@ -46,7 +46,7 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-10.15]
|
||||
os: [macos-11]
|
||||
compiler: [clang]
|
||||
configure:
|
||||
- {label: "with parser generation", opt: "--enable-parser-generation" }
|
||||
|
|
@ -73,5 +73,3 @@ jobs:
|
|||
run: make -j `sysctl -n hw.logicalcpu`
|
||||
- name: check
|
||||
run: make check
|
||||
- name: check-static
|
||||
run: make check-static
|
||||
|
|
|
|||
29
CHANGES
29
CHANGES
|
|
@ -1,3 +1,32 @@
|
|||
v3.0.10 - 2023-Jul-25
|
||||
---------------------
|
||||
|
||||
- Fix: worst-case time in implementation of four transformations
|
||||
[Issue #2934 - @martinhsv]
|
||||
- Add TX synonym for MSC_PCRE_LIMITS_EXCEEDED
|
||||
[Issue #2901 - @airween]
|
||||
- Make MULTIPART_PART_HEADERS accessible to lua
|
||||
[Issue #2916 - @martinhsv]
|
||||
- Fix: Lua scripts cannot read whole collection at once
|
||||
[Issue #2900 - @udi-aharon, @airween, @martinhsv]
|
||||
- Fix: quoted Include config with wildcard
|
||||
[Issue #2905 - @wiseelf, @airween, @martinhsv]
|
||||
- Support isolated PCRE match limits
|
||||
[Issue #2736 - @brandonpayton, @martinhsv]
|
||||
- Fix: meta actions not applied if multiMatch in first rule of chain
|
||||
[Issue #2867, #2868 - @mlevogiannis, @martinhsv]
|
||||
- Fix: audit log may omit tags when multiMatch
|
||||
[Issue #2866 - @mlevogiannis]
|
||||
- Exclude CRLF from MULTIPART_PART_HEADER value
|
||||
[Issue #2870 - @airween, @martinhsv]
|
||||
- Configure: use AS_ECHO_N instead echo -n
|
||||
[Issue #2894 - @liudongmiao, @martinhsv]
|
||||
- Adjust position of memset from 2890
|
||||
[Issue #2891 - @mirkodziadzka-avi, @martinhsv]
|
||||
- Add test: empty lines in ipMatchFromFile test
|
||||
[Issue #2846 - @tomsommer]
|
||||
|
||||
|
||||
v3.0.9 - 2023-Apr-12
|
||||
--------------------
|
||||
|
||||
|
|
|
|||
20
configure.ac
20
configure.ac
|
|
@ -424,9 +424,9 @@ echo " "
|
|||
echo "ModSecurity - ${MSC_GIT_VERSION} for $PLATFORM"
|
||||
echo " "
|
||||
echo " Mandatory dependencies"
|
||||
echo -n " + libInjection ...."
|
||||
AS_ECHO_N(" + libInjection ....")
|
||||
echo LIBINJECTION_VERSION
|
||||
echo -n " + SecLang tests ...."
|
||||
AS_ECHO_N(" + SecLang tests ....")
|
||||
echo SECLANG_TEST_VERSION
|
||||
|
||||
echo " "
|
||||
|
|
@ -439,7 +439,7 @@ if test "x$GEOIP_FOUND" = "x0" && test "x$MAXMIND_FOUND" = "x0"; then
|
|||
echo " + GeoIP/MaxMind ....not found"
|
||||
fi
|
||||
if test "x$GEOIP_FOUND" = "x1" || test "x$MAXMIND_FOUND" = "x1"; then
|
||||
echo -n " + GeoIP/MaxMind ....found "
|
||||
AS_ECHO_N(" + GeoIP/MaxMind ....found ")
|
||||
echo ""
|
||||
if test "x$MAXMIND_FOUND" = "x1"; then
|
||||
echo " * (MaxMind) v${MAXMIND_VERSION}"
|
||||
|
|
@ -460,7 +460,7 @@ if test "x$CURL_FOUND" = "x0"; then
|
|||
echo " + LibCURL ....not found"
|
||||
fi
|
||||
if test "x$CURL_FOUND" = "x1"; then
|
||||
echo -n " + LibCURL ....found "
|
||||
AS_ECHO_N(" + LibCURL ....found ")
|
||||
if ! test "x$CURL_VERSION" = "x"; then
|
||||
echo "v${CURL_VERSION}"
|
||||
else
|
||||
|
|
@ -478,7 +478,7 @@ if test "x$YAJL_FOUND" = "x0"; then
|
|||
echo " + YAJL ....not found"
|
||||
fi
|
||||
if test "x$YAJL_FOUND" = "x1"; then
|
||||
echo -n " + YAJL ....found "
|
||||
AS_ECHO_N(" + YAJL ....found ")
|
||||
if ! test "x$YAJL_VERSION" = "x"; then
|
||||
echo "v${YAJL_VERSION}"
|
||||
else
|
||||
|
|
@ -496,7 +496,7 @@ if test "x$LMDB_FOUND" = "x0"; then
|
|||
echo " + LMDB ....not found"
|
||||
fi
|
||||
if test "x$LMDB_FOUND" = "x1"; then
|
||||
echo -n " + LMDB ....found "
|
||||
AS_ECHO_N(" + LMDB ....found ")
|
||||
if ! test "x$LMDB_VERSION" = "x"; then
|
||||
echo "v${LMDB_VERSION}"
|
||||
else
|
||||
|
|
@ -514,7 +514,7 @@ if test "x$LIBXML2_FOUND" = "x0"; then
|
|||
echo " + LibXML2 ....not found"
|
||||
fi
|
||||
if test "x$LIBXML2_FOUND" = "x1"; then
|
||||
echo -n " + LibXML2 ....found "
|
||||
AS_ECHO_N(" + LibXML2 ....found ")
|
||||
if ! test "x$LIBXML2_VERSION" = "x"; then
|
||||
echo "v${LIBXML2_VERSION}"
|
||||
else
|
||||
|
|
@ -532,7 +532,7 @@ if test "x$SSDEEP_FOUND" = "x0"; then
|
|||
echo " + SSDEEP ....not found"
|
||||
fi
|
||||
if test "x$SSDEEP_FOUND" = "x1"; then
|
||||
echo -n " + SSDEEP ....found "
|
||||
AS_ECHO_N(" + SSDEEP ....found ")
|
||||
if ! test "x$SSDEEP_VERSION" = "x"; then
|
||||
echo "v${SSDEEP_VERSION}"
|
||||
else
|
||||
|
|
@ -549,7 +549,7 @@ if test "x$LUA_FOUND" = "x0"; then
|
|||
echo " + LUA ....not found"
|
||||
fi
|
||||
if test "x$LUA_FOUND" = "x1"; then
|
||||
echo -n " + LUA ....found "
|
||||
AS_ECHO_N(" + LUA ....found ")
|
||||
if ! test "x$LUA_VERSION" = "x"; then
|
||||
echo "v${LUA_VERSION}"
|
||||
else
|
||||
|
|
@ -567,7 +567,7 @@ if test "x$PCRE2_FOUND" = "x0"; then
|
|||
echo " + PCRE2 ....not found"
|
||||
fi
|
||||
if test "x$PCRE2_FOUND" = "x1"; then
|
||||
echo -n " + PCRE2 ....found "
|
||||
AS_ECHO_N(" + PCRE2 ....found ")
|
||||
if ! test "x$PCRE2_VERSION" = "x"; then
|
||||
echo "v${PCRE2_VERSION}"
|
||||
else
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ namespace modsecurity {
|
|||
|
||||
#define MODSECURITY_MAJOR "3"
|
||||
#define MODSECURITY_MINOR "0"
|
||||
#define MODSECURITY_PATCHLEVEL "9"
|
||||
#define MODSECURITY_PATCHLEVEL "10"
|
||||
#define MODSECURITY_TAG ""
|
||||
#define MODSECURITY_TAG_NUM "100"
|
||||
|
||||
|
|
@ -198,7 +198,7 @@ namespace modsecurity {
|
|||
MODSECURITY_MINOR "." MODSECURITY_PATCHLEVEL \
|
||||
MODSECURITY_TAG
|
||||
|
||||
#define MODSECURITY_VERSION_NUM 3090100
|
||||
#define MODSECURITY_VERSION_NUM 30100100
|
||||
|
||||
#define MODSECURITY_CHECK_VERSION(a) (MODSECURITY_VERSION_NUM <= a)
|
||||
|
||||
|
|
|
|||
|
|
@ -379,6 +379,7 @@ class RulesSetProperties {
|
|||
from->m_responseBodyLimitAction,
|
||||
PropertyNotSetBodyLimitAction);
|
||||
|
||||
to->m_pcreMatchLimit.merge(&from->m_pcreMatchLimit);
|
||||
to->m_uploadFileLimit.merge(&from->m_uploadFileLimit);
|
||||
to->m_uploadFileMode.merge(&from->m_uploadFileMode);
|
||||
to->m_uploadDirectory.merge(&from->m_uploadDirectory);
|
||||
|
|
@ -470,6 +471,7 @@ class RulesSetProperties {
|
|||
ConfigDouble m_requestBodyLimit;
|
||||
ConfigDouble m_requestBodyNoFilesLimit;
|
||||
ConfigDouble m_responseBodyLimit;
|
||||
ConfigInt m_pcreMatchLimit;
|
||||
ConfigInt m_uploadFileLimit;
|
||||
ConfigInt m_uploadFileMode;
|
||||
DebugLog *m_debugLog;
|
||||
|
|
|
|||
|
|
@ -134,6 +134,8 @@ class TransactionAnchoredVariables {
|
|||
m_variableInboundDataError(t, "INBOUND_DATA_ERROR"),
|
||||
m_variableMatchedVar(t, "MATCHED_VAR"),
|
||||
m_variableMatchedVarName(t, "MATCHED_VAR_NAME"),
|
||||
m_variableMscPcreError(t, "MSC_PCRE_ERROR"),
|
||||
m_variableMscPcreLimitsExceeded(t, "MSC_PCRE_LIMITS_EXCEEDED"),
|
||||
m_variableMultipartBoundaryQuoted(t, "MULTIPART_BOUNDARY_QUOTED"),
|
||||
m_variableMultipartBoundaryWhiteSpace(t,
|
||||
"MULTIPART_BOUNDARY_WHITESPACE"),
|
||||
|
|
@ -219,6 +221,8 @@ class TransactionAnchoredVariables {
|
|||
AnchoredVariable m_variableInboundDataError;
|
||||
AnchoredVariable m_variableMatchedVar;
|
||||
AnchoredVariable m_variableMatchedVarName;
|
||||
AnchoredVariable m_variableMscPcreError;
|
||||
AnchoredVariable m_variableMscPcreLimitsExceeded;
|
||||
AnchoredVariable m_variableMultipartBoundaryQuoted;
|
||||
AnchoredVariable m_variableMultipartBoundaryWhiteSpace;
|
||||
AnchoredVariable m_variableMultipartCrlfLFLines;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
* Copyright (c) 2015 - 2023 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
|
|
@ -15,12 +15,7 @@
|
|||
|
||||
#include "src/actions/transformations/remove_comments_char.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <cctype>
|
||||
#include <locale>
|
||||
|
||||
#include "modsecurity/transaction.h"
|
||||
#include "src/actions/transformations/transformation.h"
|
||||
|
|
@ -37,39 +32,40 @@ RemoveCommentsChar::RemoveCommentsChar(const std::string &action)
|
|||
|
||||
std::string RemoveCommentsChar::evaluate(const std::string &val,
|
||||
Transaction *transaction) {
|
||||
int64_t i;
|
||||
std::string value(val);
|
||||
size_t i = 0;
|
||||
std::string transformed_value;
|
||||
transformed_value.reserve(val.size());
|
||||
|
||||
i = 0;
|
||||
while (i < value.size()) {
|
||||
if (value.at(i) == '/'
|
||||
&& (i+1 < value.size()) && value.at(i+1) == '*') {
|
||||
value.erase(i, 2);
|
||||
} else if (value.at(i) == '*'
|
||||
&& (i+1 < value.size()) && value.at(i+1) == '/') {
|
||||
value.erase(i, 2);
|
||||
} else if (value.at(i) == '<'
|
||||
&& (i+1 < value.size())
|
||||
&& value.at(i+1) == '!'
|
||||
&& (i+2 < value.size())
|
||||
&& value.at(i+2) == '-'
|
||||
&& (i+3 < value.size())
|
||||
&& value.at(i+3) == '-') {
|
||||
value.erase(i, 4);
|
||||
} else if (value.at(i) == '-'
|
||||
&& (i+1 < value.size()) && value.at(i+1) == '-'
|
||||
&& (i+2 < value.size()) && value.at(i+2) == '>') {
|
||||
value.erase(i, 3);
|
||||
} else if (value.at(i) == '-'
|
||||
&& (i+1 < value.size()) && value.at(i+1) == '-') {
|
||||
value.erase(i, 2);
|
||||
} else if (value.at(i) == '#') {
|
||||
value.erase(i, 1);
|
||||
while (i < val.size()) {
|
||||
if (val.at(i) == '/'
|
||||
&& (i+1 < val.size()) && val.at(i+1) == '*') {
|
||||
i += 2;
|
||||
} else if (val.at(i) == '*'
|
||||
&& (i+1 < val.size()) && val.at(i+1) == '/') {
|
||||
i += 2;
|
||||
} else if (val.at(i) == '<'
|
||||
&& (i+1 < val.size())
|
||||
&& val.at(i+1) == '!'
|
||||
&& (i+2 < val.size())
|
||||
&& val.at(i+2) == '-'
|
||||
&& (i+3 < val.size())
|
||||
&& val.at(i+3) == '-') {
|
||||
i += 4;
|
||||
} else if (val.at(i) == '-'
|
||||
&& (i+1 < val.size()) && val.at(i+1) == '-'
|
||||
&& (i+2 < val.size()) && val.at(i+2) == '>') {
|
||||
i += 3;
|
||||
} else if (val.at(i) == '-'
|
||||
&& (i+1 < val.size()) && val.at(i+1) == '-') {
|
||||
i += 2;
|
||||
} else if (val.at(i) == '#') {
|
||||
i += 1;
|
||||
} else {
|
||||
transformed_value += val.at(i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
return transformed_value;
|
||||
}
|
||||
|
||||
} // namespace transformations
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
* Copyright (c) 2015 - 2023 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
|
|
@ -17,12 +17,7 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <cctype>
|
||||
#include <locale>
|
||||
|
||||
#include "modsecurity/transaction.h"
|
||||
#include "src/actions/transformations/transformation.h"
|
||||
|
|
@ -35,19 +30,20 @@ namespace transformations {
|
|||
|
||||
std::string RemoveNulls::evaluate(const std::string &val,
|
||||
Transaction *transaction) {
|
||||
int64_t i;
|
||||
std::string value(val);
|
||||
size_t i = 0;
|
||||
std::string transformed_value;
|
||||
transformed_value.reserve(val.size());
|
||||
|
||||
i = 0;
|
||||
while (i < value.size()) {
|
||||
if (value.at(i) == '\0') {
|
||||
value.erase(i, 1);
|
||||
while (i < val.size()) {
|
||||
if (val.at(i) == '\0') {
|
||||
// do nothing; continue on to next char in original val
|
||||
} else {
|
||||
i++;
|
||||
transformed_value += val.at(i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return value;
|
||||
return transformed_value;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
* Copyright (c) 2015 - 2023 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
|
|
@ -15,12 +15,7 @@
|
|||
|
||||
#include "src/actions/transformations/remove_whitespace.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <cctype>
|
||||
#include <locale>
|
||||
|
||||
#include "modsecurity/transaction.h"
|
||||
#include "src/actions/transformations/transformation.h"
|
||||
|
|
@ -37,28 +32,27 @@ RemoveWhitespace::RemoveWhitespace(const std::string &action)
|
|||
|
||||
std::string RemoveWhitespace::evaluate(const std::string &val,
|
||||
Transaction *transaction) {
|
||||
std::string value(val);
|
||||
std::string transformed_value;
|
||||
transformed_value.reserve(val.size());
|
||||
|
||||
int64_t i = 0;
|
||||
size_t i = 0;
|
||||
const char nonBreakingSpaces = 0xa0;
|
||||
const char nonBreakingSpaces2 = 0xc2;
|
||||
|
||||
// loop through all the chars
|
||||
while (i < value.size()) {
|
||||
while (i < val.size()) {
|
||||
// remove whitespaces and non breaking spaces (NBSP)
|
||||
if (std::isspace(static_cast<unsigned char>(value[i]))
|
||||
|| (value[i] == nonBreakingSpaces)
|
||||
|| value[i] == nonBreakingSpaces2) {
|
||||
value.erase(i, 1);
|
||||
if (std::isspace(static_cast<unsigned char>(val[i]))
|
||||
|| (val[i] == nonBreakingSpaces)
|
||||
|| val[i] == nonBreakingSpaces2) {
|
||||
// don't copy; continue on to next char in original val
|
||||
} else {
|
||||
/* if the space is not a whitespace char, increment counter
|
||||
counter should not be incremented if a character is erased because
|
||||
the index erased will be replaced by the following character */
|
||||
i++;
|
||||
transformed_value += val.at(i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return value;
|
||||
return transformed_value;
|
||||
}
|
||||
|
||||
} // namespace transformations
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
* Copyright (c) 2015 - 2023 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
|
|
@ -15,12 +15,7 @@
|
|||
|
||||
#include "src/actions/transformations/replace_nulls.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <cctype>
|
||||
#include <locale>
|
||||
|
||||
#include "modsecurity/transaction.h"
|
||||
#include "src/actions/transformations/transformation.h"
|
||||
|
|
@ -43,8 +38,7 @@ std::string ReplaceNulls::evaluate(const std::string &val,
|
|||
i = 0;
|
||||
while (i < value.size()) {
|
||||
if (value.at(i) == '\0') {
|
||||
value.erase(i, 1);
|
||||
value.insert(i, " ", 1);
|
||||
value[i] = ' ';
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace backend {
|
|||
|
||||
#ifdef WITH_LMDB
|
||||
|
||||
LMDB::LMDB(std::string name) :
|
||||
LMDB::LMDB(const std::string &name) :
|
||||
Collection(name), m_env(NULL), isOpen(false) {}
|
||||
|
||||
int LMDB::txn_begin(unsigned int flags, MDB_txn **ret) {
|
||||
|
|
@ -60,7 +60,7 @@ void LMDB::string2val(const std::string& str, MDB_val *val) {
|
|||
}
|
||||
|
||||
|
||||
void LMDB::lmdb_debug(int rc, std::string op, std::string scope) {
|
||||
void LMDB::lmdb_debug(int rc, const std::string &op, const std::string &scope) {
|
||||
#ifndef LMDB_STDOUT_COUT
|
||||
return;
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ class MDBEnvProvider {
|
|||
class LMDB :
|
||||
public Collection {
|
||||
public:
|
||||
explicit LMDB(std::string name);
|
||||
explicit LMDB(const std::string &name);
|
||||
void store(std::string key, std::string value) override;
|
||||
|
||||
bool storeOrUpdateFirst(const std::string &key,
|
||||
|
|
@ -122,7 +122,7 @@ class LMDB :
|
|||
private:
|
||||
int txn_begin(unsigned int flags, MDB_txn **ret);
|
||||
void string2val(const std::string& str, MDB_val *val);
|
||||
void inline lmdb_debug(int rc, std::string op, std::string scope);
|
||||
void inline lmdb_debug(int rc, const std::string &op, const std::string &scope);
|
||||
|
||||
MDB_env *m_env;
|
||||
MDB_dbi m_dbi;
|
||||
|
|
|
|||
|
|
@ -51,12 +51,38 @@ bool Rx::evaluate(Transaction *transaction, RuleWithActions *rule,
|
|||
re = m_re;
|
||||
}
|
||||
|
||||
std::vector<Utils::SMatchCapture> captures;
|
||||
if (re->hasError()) {
|
||||
ms_dbg_a(transaction, 3, "Error with regular expression: \"" + re->pattern + "\"");
|
||||
return false;
|
||||
}
|
||||
re->searchOneMatch(input, captures);
|
||||
|
||||
Utils::RegexResult regex_result;
|
||||
std::vector<Utils::SMatchCapture> captures;
|
||||
|
||||
if (transaction && transaction->m_rules->m_pcreMatchLimit.m_set) {
|
||||
unsigned long match_limit = transaction->m_rules->m_pcreMatchLimit.m_value;
|
||||
regex_result = re->searchOneMatch(input, captures, match_limit);
|
||||
} else {
|
||||
regex_result = re->searchOneMatch(input, captures);
|
||||
}
|
||||
|
||||
// FIXME: DRY regex error reporting. This logic is currently duplicated in other operators.
|
||||
if (regex_result != Utils::RegexResult::Ok) {
|
||||
transaction->m_variableMscPcreError.set("1", transaction->m_variableOffset);
|
||||
|
||||
std::string regex_error_str = "OTHER";
|
||||
if (regex_result == Utils::RegexResult::ErrorMatchLimit) {
|
||||
regex_error_str = "MATCH_LIMIT";
|
||||
transaction->m_variableMscPcreLimitsExceeded.set("1", transaction->m_variableOffset);
|
||||
transaction->m_collections.m_tx_collection->storeOrUpdateFirst("MSC_PCRE_LIMITS_EXCEEDED", "1");
|
||||
ms_dbg_a(transaction, 7, "Set TX.MSC_PCRE_LIMITS_EXCEEDED to 1");
|
||||
}
|
||||
|
||||
ms_dbg_a(transaction, 1, "rx: regex error '" + regex_error_str + "' for pattern '" + re->pattern + "'");
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rule && rule->hasCaptureAction() && transaction) {
|
||||
for (const Utils::SMatchCapture& capture : captures) {
|
||||
|
|
|
|||
|
|
@ -51,8 +51,32 @@ bool RxGlobal::evaluate(Transaction *transaction, RuleWithActions *rule,
|
|||
re = m_re;
|
||||
}
|
||||
|
||||
Utils::RegexResult regex_result;
|
||||
std::vector<Utils::SMatchCapture> captures;
|
||||
re->searchGlobal(input, captures);
|
||||
if (transaction && transaction->m_rules->m_pcreMatchLimit.m_set) {
|
||||
unsigned long match_limit = transaction->m_rules->m_pcreMatchLimit.m_value;
|
||||
regex_result = re->searchGlobal(input, captures, match_limit);
|
||||
} else {
|
||||
regex_result = re->searchGlobal(input, captures);
|
||||
}
|
||||
|
||||
// FIXME: DRY regex error reporting. This logic is currently duplicated in other operators.
|
||||
if (regex_result != Utils::RegexResult::Ok) {
|
||||
transaction->m_variableMscPcreError.set("1", transaction->m_variableOffset);
|
||||
|
||||
std::string regex_error_str = "OTHER";
|
||||
if (regex_result == Utils::RegexResult::ErrorMatchLimit) {
|
||||
regex_error_str = "MATCH_LIMIT";
|
||||
transaction->m_variableMscPcreLimitsExceeded.set("1", transaction->m_variableOffset);
|
||||
transaction->m_collections.m_tx_collection->storeOrUpdateFirst("MSC_PCRE_LIMITS_EXCEEDED", "1");
|
||||
ms_dbg_a(transaction, 7, "Set TX.MSC_PCRE_LIMITS_EXCEEDED to 1");
|
||||
}
|
||||
|
||||
ms_dbg_a(transaction, 1, "rxGlobal: regex error '" + regex_error_str + "' for pattern '" + re->pattern + "'");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (rule && rule->hasCaptureAction() && transaction) {
|
||||
for (const Utils::SMatchCapture& capture : captures) {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ Driver::~Driver() {
|
|||
}
|
||||
|
||||
|
||||
int Driver::addSecMarker(std::string marker, std::unique_ptr<std::string> fileName, int lineNumber) {
|
||||
int Driver::addSecMarker(const std::string& marker, std::unique_ptr<std::string> fileName, int lineNumber) {
|
||||
// FIXME: we might move this to the parser.
|
||||
for (int i = 0; i < modsecurity::Phases::NUMBER_OF_PHASES; i++) {
|
||||
RuleMarker *r = new RuleMarker(marker, std::unique_ptr<std::string>(new std::string(*fileName)), lineNumber);
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class Driver : public RulesSetProperties {
|
|||
|
||||
int addSecRule(std::unique_ptr<RuleWithActions> rule);
|
||||
int addSecAction(std::unique_ptr<RuleWithActions> rule);
|
||||
int addSecMarker(std::string marker, std::unique_ptr<std::string> fileName, int lineNumber);
|
||||
int addSecMarker(const std::string& marker, std::unique_ptr<std::string> fileName, int lineNumber);
|
||||
int addSecRuleScript(std::unique_ptr<RuleScript> rule);
|
||||
|
||||
bool scan_begin();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// A Bison parser, made by GNU Bison 3.7.6.
|
||||
// A Bison parser, made by GNU Bison 3.8.2.
|
||||
|
||||
// Locations for Bison parsers in C++
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// A Bison parser, made by GNU Bison 3.7.6.
|
||||
// A Bison parser, made by GNU Bison 3.8.2.
|
||||
|
||||
// Starting with Bison 3.2, this file is useless: the structure it
|
||||
// used to define is now defined in "location.hh".
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -184,6 +184,8 @@ class Driver;
|
|||
#include "src/variables/matched_vars.h"
|
||||
#include "src/variables/matched_vars_names.h"
|
||||
#include "src/variables/modsec_build.h"
|
||||
#include "src/variables/msc_pcre_error.h"
|
||||
#include "src/variables/msc_pcre_limits_exceeded.h"
|
||||
#include "src/variables/multipart_boundary_quoted.h"
|
||||
#include "src/variables/multipart_boundary_whitespace.h"
|
||||
#include "src/variables/multipart_crlf_lf_lines.h"
|
||||
|
|
@ -368,6 +370,8 @@ using namespace modsecurity::operators;
|
|||
VARIABLE_INBOUND_DATA_ERROR "INBOUND_DATA_ERROR"
|
||||
VARIABLE_MATCHED_VAR "MATCHED_VAR"
|
||||
VARIABLE_MATCHED_VAR_NAME "MATCHED_VAR_NAME"
|
||||
VARIABLE_MSC_PCRE_ERROR "MSC_PCRE_ERROR"
|
||||
VARIABLE_MSC_PCRE_LIMITS_EXCEEDED "MSC_PCRE_LIMITS_EXCEEDED"
|
||||
VARIABLE_MULTIPART_BOUNDARY_QUOTED
|
||||
VARIABLE_MULTIPART_BOUNDARY_WHITESPACE
|
||||
VARIABLE_MULTIPART_CRLF_LF_LINES "MULTIPART_CRLF_LF_LINES"
|
||||
|
|
@ -1648,10 +1652,10 @@ expression:
|
|||
YYERROR;
|
||||
*/
|
||||
| CONFIG_DIR_PCRE_MATCH_LIMIT
|
||||
/* Parser error disabled to avoid breaking default installations with modsecurity.conf-recommended
|
||||
driver.error(@0, "SecPcreMatchLimit is not currently supported. Default PCRE values are being used for now");
|
||||
YYERROR;
|
||||
*/
|
||||
{
|
||||
driver.m_pcreMatchLimit.m_set = true;
|
||||
driver.m_pcreMatchLimit.m_value = atoi($1.c_str());
|
||||
}
|
||||
| CONGIG_DIR_RESPONSE_BODY_MP
|
||||
{
|
||||
std::istringstream buf($1);
|
||||
|
|
@ -2321,6 +2325,14 @@ var:
|
|||
{
|
||||
VARIABLE_CONTAINER($$, new variables::MatchedVarName());
|
||||
}
|
||||
| VARIABLE_MSC_PCRE_ERROR
|
||||
{
|
||||
VARIABLE_CONTAINER($$, new variables::MscPcreError());
|
||||
}
|
||||
| VARIABLE_MSC_PCRE_LIMITS_EXCEEDED
|
||||
{
|
||||
VARIABLE_CONTAINER($$, new variables::MscPcreLimitsExceeded());
|
||||
}
|
||||
| VARIABLE_MULTIPART_BOUNDARY_QUOTED
|
||||
{
|
||||
VARIABLE_CONTAINER($$, new variables::MultipartBoundaryQuoted());
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -186,6 +186,8 @@ VARIABLE_GLOBAL (?i:GLOBAL)
|
|||
VARIABLE_INBOUND_DATA_ERROR (?i:INBOUND_DATA_ERROR)
|
||||
VARIABLE_MATCHED_VAR (?i:MATCHED_VAR)
|
||||
VARIABLE_MATCHED_VAR_NAME (?i:MATCHED_VAR_NAME)
|
||||
VARIABLE_MSC_PCRE_ERROR (?i:MSC_PCRE_ERROR)
|
||||
VARIABLE_MSC_PCRE_LIMITS_EXCEEDED (?i:MSC_PCRE_LIMITS_EXCEEDED)
|
||||
VARIABLE_MULTIPART_BOUNDARY_QUOTED (?i:MULTIPART_BOUNDARY_QUOTED)
|
||||
VARIABLE_MULTIPART_BOUNDARY_WHITESPACE (?i:MULTIPART_BOUNDARY_WHITESPACE)
|
||||
VARIABLE_MULTIPART_CRLF_LF_LINES (?i:MULTIPART_CRLF_LF_LINES)
|
||||
|
|
@ -910,6 +912,8 @@ EQUALS_MINUS (?i:=\-)
|
|||
{VARIABLE_INBOUND_DATA_ERROR} { return p::make_VARIABLE_INBOUND_DATA_ERROR(*driver.loc.back()); }
|
||||
{VARIABLE_MATCHED_VAR_NAME} { return p::make_VARIABLE_MATCHED_VAR_NAME(*driver.loc.back()); }
|
||||
{VARIABLE_MATCHED_VAR} { return p::make_VARIABLE_MATCHED_VAR(*driver.loc.back()); }
|
||||
{VARIABLE_MSC_PCRE_ERROR} { return p::make_VARIABLE_MSC_PCRE_ERROR(*driver.loc.back()); }
|
||||
{VARIABLE_MSC_PCRE_LIMITS_EXCEEDED} { return p::make_VARIABLE_MSC_PCRE_LIMITS_EXCEEDED(*driver.loc.back()); }
|
||||
{VARIABLE_MULTIPART_BOUNDARY_QUOTED} { return p::make_VARIABLE_MULTIPART_BOUNDARY_QUOTED(*driver.loc.back()); }
|
||||
{VARIABLE_MULTIPART_BOUNDARY_WHITESPACE} { return p::make_VARIABLE_MULTIPART_BOUNDARY_WHITESPACE(*driver.loc.back()); }
|
||||
{VARIABLE_MULTIPART_CRLF_LF_LINES} { return p::make_VARIABLE_MULTIPART_CRLF_LF_LINES(*driver.loc.back()); }
|
||||
|
|
@ -1271,9 +1275,9 @@ EQUALS_MINUS (?i:=\-)
|
|||
{CONFIG_INCLUDE}[ \t]+["]{CONFIG_VALUE_PATH}["] {
|
||||
std::string err;
|
||||
const char *tmpStr = yytext + strlen("include");
|
||||
const char *file = tmpStr + strspn( tmpStr, " \t");
|
||||
char *f = strdup(file);
|
||||
std::string fi = modsecurity::utils::find_resource(f, *driver.loc.back()->end.filename, &err);
|
||||
const char *afterWhitespace = tmpStr + strspn( tmpStr, " \t");
|
||||
std::string file(afterWhitespace+1, strlen(afterWhitespace)-2);
|
||||
std::string fi = modsecurity::utils::find_resource(file, *driver.loc.back()->end.filename, &err);
|
||||
if (fi.empty() == true) {
|
||||
BEGIN(INITIAL);
|
||||
driver.error (*driver.loc.back(), "", file + std::string(": Not able to open file. ") + err);
|
||||
|
|
@ -1296,7 +1300,6 @@ EQUALS_MINUS (?i:=\-)
|
|||
}
|
||||
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
|
||||
}
|
||||
free(f);
|
||||
}
|
||||
|
||||
{CONFIG_SEC_REMOTE_RULES}[ ][^ ]+[ ][^\n\r ]+ {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// A Bison parser, made by GNU Bison 3.7.6.
|
||||
// A Bison parser, made by GNU Bison 3.8.2.
|
||||
|
||||
// Starting with Bison 3.2, this file is useless: the structure it
|
||||
// used to define is now defined with the parser itself.
|
||||
|
|
|
|||
|
|
@ -935,7 +935,7 @@ int Multipart::process_part_header(std::string *error, int offset) {
|
|||
"Multipart: Added part header \"" + header_name \
|
||||
+ "\" \"" + header_value + "\".");
|
||||
if (len_without_termination > 0) {
|
||||
m_mpp->m_last_header_line.assign(m_buf);
|
||||
m_mpp->m_last_header_line.assign(m_buf, len_without_termination);
|
||||
} else {
|
||||
m_mpp->m_last_header_line.assign("");
|
||||
}
|
||||
|
|
@ -1198,15 +1198,9 @@ int Multipart::multipart_complete(std::string *error) {
|
|||
size_t offset = m_transaction->m_variableOffset + 1;
|
||||
|
||||
if (m->m_type == MULTIPART_FILE) {
|
||||
std::string tmp_name;
|
||||
std::string name;
|
||||
if (m->m_tmp_file && !m->m_tmp_file->getFilename().empty()) {
|
||||
tmp_name.assign(m->m_tmp_file->getFilename());
|
||||
m_transaction->m_variableFilesTmpNames.set(m->m_tmp_file->getFilename(),
|
||||
m->m_tmp_file->getFilename(), m->m_filenameOffset);
|
||||
}
|
||||
if (!m->m_filename.empty()) {
|
||||
name.assign(m->m_filename);
|
||||
if (m->m_tmp_file && !m->m_tmp_file->getFilename().empty()) {
|
||||
m_transaction->m_variableFilesTmpNames.set(m->m_tmp_file->getFilename(),
|
||||
m->m_tmp_file->getFilename(), m->m_filenameOffset);
|
||||
}
|
||||
|
||||
m_transaction->m_variableFiles.set(m->m_name,
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ void RuleWithActions::executeActionsIndependentOfChainedRuleResult(Transaction *
|
|||
}
|
||||
}
|
||||
|
||||
if (m_containsMultiMatchAction && !m_isChained) {
|
||||
if (m_containsMultiMatchAction && m_chainedRuleParent == nullptr) {
|
||||
if (m_severity) {
|
||||
m_severity->evaluate(this, trans, ruleMessage);
|
||||
}
|
||||
|
|
@ -229,6 +229,9 @@ void RuleWithActions::executeActionsIndependentOfChainedRuleResult(Transaction *
|
|||
if (m_msg) {
|
||||
m_msg->evaluate(this, trans, ruleMessage);
|
||||
}
|
||||
for (actions::Tag *a : m_actionsTag) {
|
||||
a->evaluate(this, trans, ruleMessage);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,6 +167,8 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, void *logCbData)
|
|||
+ std::to_string(modsecurity::utils::generate_transaction_unique_id())));
|
||||
|
||||
m_variableUrlEncodedError.set("0", 0);
|
||||
m_variableMscPcreError.set("0", 0);
|
||||
m_variableMscPcreLimitsExceeded.set("0", 0);
|
||||
|
||||
ms_dbg(4, "Initializing transaction");
|
||||
|
||||
|
|
@ -238,6 +240,8 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, char *id, void *logCb
|
|||
TransactionAnchoredVariables(this) {
|
||||
|
||||
m_variableUrlEncodedError.set("0", 0);
|
||||
m_variableMscPcreError.set("0", 0);
|
||||
m_variableMscPcreLimitsExceeded.set("0", 0);
|
||||
|
||||
ms_dbg(4, "Initializing transaction");
|
||||
|
||||
|
|
|
|||
|
|
@ -258,11 +258,13 @@ int InsertNetmask(TreeNode *node, TreeNode *parent, TreeNode *new_node,
|
|||
}
|
||||
|
||||
node->count++;
|
||||
|
||||
node->netmasks = reinterpret_cast<unsigned char *>(malloc(node->count * sizeof(unsigned char)));
|
||||
if(node->netmasks == NULL) {
|
||||
return 0;
|
||||
}
|
||||
memset(node->netmasks, 0, (node->count * sizeof(unsigned char)));
|
||||
|
||||
if(node->netmasks == NULL)
|
||||
return 0;
|
||||
if ((node->count-1) == 0) {
|
||||
node->netmasks[0] = netmask;
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -25,12 +25,38 @@
|
|||
|
||||
#ifndef WITH_PCRE2
|
||||
#if PCRE_HAVE_JIT
|
||||
#define pcre_study_opt PCRE_STUDY_JIT_COMPILE
|
||||
// NOTE: Add PCRE_STUDY_EXTRA_NEEDED so studying always yields a pcre_extra strucure
|
||||
// and we can selectively override match limits using a copy of that structure at runtime.
|
||||
#define pcre_study_opt PCRE_STUDY_JIT_COMPILE | PCRE_STUDY_EXTRA_NEEDED
|
||||
#else
|
||||
#define pcre_study_opt 0
|
||||
// NOTE: Add PCRE_STUDY_EXTRA_NEEDED so studying always yields a pcre_extra strucure
|
||||
// and we can selectively override match limits using a copy of that structure at runtime.
|
||||
#define pcre_study_opt PCRE_STUDY_EXTRA_NEEDED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PCRE2
|
||||
class Pcre2MatchContextPtr {
|
||||
public:
|
||||
Pcre2MatchContextPtr()
|
||||
: m_match_context(pcre2_match_context_create(NULL)) {}
|
||||
|
||||
Pcre2MatchContextPtr(const Pcre2MatchContextPtr&) = delete;
|
||||
Pcre2MatchContextPtr& operator=(const Pcre2MatchContextPtr&) = delete;
|
||||
|
||||
~Pcre2MatchContextPtr() {
|
||||
pcre2_match_context_free(m_match_context);
|
||||
}
|
||||
|
||||
operator pcre2_match_context*() const {
|
||||
return m_match_context;
|
||||
}
|
||||
|
||||
private:
|
||||
pcre2_match_context *m_match_context;
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace modsecurity {
|
||||
namespace Utils {
|
||||
|
||||
|
|
@ -163,24 +189,39 @@ std::list<SMatch> Regex::searchAll(const std::string& s) const {
|
|||
return retList;
|
||||
}
|
||||
|
||||
bool Regex::searchOneMatch(const std::string& s, std::vector<SMatchCapture>& captures) const {
|
||||
RegexResult Regex::searchOneMatch(const std::string& s, std::vector<SMatchCapture>& captures, unsigned long match_limit) const {
|
||||
#ifdef WITH_PCRE2
|
||||
Pcre2MatchContextPtr match_context;
|
||||
if (match_limit > 0) {
|
||||
// TODO: What if setting the match limit fails?
|
||||
pcre2_set_match_limit(match_context, match_limit);
|
||||
}
|
||||
|
||||
PCRE2_SPTR pcre2_s = reinterpret_cast<PCRE2_SPTR>(s.c_str());
|
||||
pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_pc, NULL);
|
||||
int rc = 0;
|
||||
if (m_pcje == 0) {
|
||||
rc = pcre2_jit_match(m_pc, pcre2_s, s.length(), 0, 0, match_data, NULL);
|
||||
rc = pcre2_jit_match(m_pc, pcre2_s, s.length(), 0, 0, match_data, match_context);
|
||||
}
|
||||
|
||||
if (m_pcje != 0 || rc == PCRE2_ERROR_JIT_STACKLIMIT) {
|
||||
rc = pcre2_match(m_pc, pcre2_s, s.length(), 0, PCRE2_NO_JIT, match_data, NULL);
|
||||
rc = pcre2_match(m_pc, pcre2_s, s.length(), 0, PCRE2_NO_JIT, match_data, match_context);
|
||||
}
|
||||
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
|
||||
#else
|
||||
const char *subject = s.c_str();
|
||||
int ovector[OVECCOUNT];
|
||||
pcre_extra local_pce;
|
||||
pcre_extra *pce = m_pce;
|
||||
|
||||
int rc = pcre_exec(m_pc, m_pce, subject, s.size(), 0, 0, ovector, OVECCOUNT);
|
||||
if (m_pce != NULL && match_limit > 0) {
|
||||
local_pce = *m_pce;
|
||||
local_pce.match_limit = match_limit;
|
||||
local_pce.flags |= PCRE_EXTRA_MATCH_LIMIT;
|
||||
pce = &local_pce;
|
||||
}
|
||||
|
||||
int rc = pcre_exec(m_pc, pce, subject, s.size(), 0, 0, ovector, OVECCOUNT);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < rc; i++) {
|
||||
|
|
@ -197,12 +238,18 @@ bool Regex::searchOneMatch(const std::string& s, std::vector<SMatchCapture>& cap
|
|||
#ifdef WITH_PCRE2
|
||||
pcre2_match_data_free(match_data);
|
||||
#endif
|
||||
return (rc > 0);
|
||||
return to_regex_result(rc);
|
||||
}
|
||||
|
||||
bool Regex::searchGlobal(const std::string& s, std::vector<SMatchCapture>& captures) const {
|
||||
RegexResult Regex::searchGlobal(const std::string& s, std::vector<SMatchCapture>& captures, unsigned long match_limit) const {
|
||||
bool prev_match_zero_length = false;
|
||||
#ifdef WITH_PCRE2
|
||||
Pcre2MatchContextPtr match_context;
|
||||
if (match_limit > 0) {
|
||||
// TODO: What if setting the match limit fails?
|
||||
pcre2_set_match_limit(match_context, match_limit);
|
||||
}
|
||||
|
||||
PCRE2_SPTR pcre2_s = reinterpret_cast<PCRE2_SPTR>(s.c_str());
|
||||
PCRE2_SIZE startOffset = 0;
|
||||
|
||||
|
|
@ -213,11 +260,21 @@ bool Regex::searchGlobal(const std::string& s, std::vector<SMatchCapture>& captu
|
|||
pcre2_options = PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED;
|
||||
}
|
||||
int rc = pcre2_match(m_pc, pcre2_s, s.length(),
|
||||
startOffset, pcre2_options, match_data, NULL);
|
||||
startOffset, pcre2_options, match_data, match_context);
|
||||
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
|
||||
|
||||
#else
|
||||
const char *subject = s.c_str();
|
||||
pcre_extra local_pce;
|
||||
pcre_extra *pce = m_pce;
|
||||
|
||||
if (m_pce != NULL && match_limit > 0) {
|
||||
local_pce = *m_pce;
|
||||
local_pce.match_limit = match_limit;
|
||||
local_pce.flags |= PCRE_EXTRA_MATCH_LIMIT;
|
||||
pce = &local_pce;
|
||||
}
|
||||
|
||||
int startOffset = 0;
|
||||
|
||||
while (startOffset <= s.length()) {
|
||||
|
|
@ -226,7 +283,12 @@ bool Regex::searchGlobal(const std::string& s, std::vector<SMatchCapture>& captu
|
|||
if (prev_match_zero_length) {
|
||||
pcre_options = PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED;
|
||||
}
|
||||
int rc = pcre_exec(m_pc, m_pce, subject, s.length(), startOffset, pcre_options, ovector, OVECCOUNT);
|
||||
int rc = pcre_exec(m_pc, pce, subject, s.length(), startOffset, pcre_options, ovector, OVECCOUNT);
|
||||
|
||||
RegexResult regex_result = to_regex_result(rc);
|
||||
if (regex_result != RegexResult::Ok) {
|
||||
return regex_result;
|
||||
}
|
||||
|
||||
#endif
|
||||
if (rc > 0) {
|
||||
|
|
@ -278,7 +340,7 @@ bool Regex::searchGlobal(const std::string& s, std::vector<SMatchCapture>& captu
|
|||
#ifdef WITH_PCRE2
|
||||
pcre2_match_data_free(match_data);
|
||||
#endif
|
||||
return (captures.size() > 0);
|
||||
return RegexResult::Ok;
|
||||
}
|
||||
|
||||
int Regex::search(const std::string& s, SMatch *match) const {
|
||||
|
|
@ -340,5 +402,30 @@ int Regex::search(const std::string& s) const {
|
|||
#endif
|
||||
}
|
||||
|
||||
RegexResult Regex::to_regex_result(int pcre_exec_result) const {
|
||||
if (
|
||||
pcre_exec_result > 0 ||
|
||||
#ifdef WITH_PCRE2
|
||||
pcre_exec_result == PCRE2_ERROR_NOMATCH
|
||||
#else
|
||||
pcre_exec_result == PCRE_ERROR_NOMATCH
|
||||
#endif
|
||||
) {
|
||||
return RegexResult::Ok;
|
||||
} else if(
|
||||
#ifdef WITH_PCRE2
|
||||
pcre_exec_result == PCRE2_ERROR_MATCHLIMIT
|
||||
#else
|
||||
pcre_exec_result == PCRE_ERROR_MATCHLIMIT
|
||||
#endif
|
||||
) {
|
||||
return RegexResult::ErrorMatchLimit;
|
||||
} else {
|
||||
// Note that this can include the case where the PCRE result was zero.
|
||||
// Zero is returned if the offset vector is not large enough and can be considered an error.
|
||||
return RegexResult::ErrorOther;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Utils
|
||||
} // namespace modsecurity
|
||||
|
|
|
|||
|
|
@ -34,6 +34,12 @@ namespace Utils {
|
|||
|
||||
#define OVECCOUNT 900
|
||||
|
||||
enum class RegexResult {
|
||||
Ok,
|
||||
ErrorMatchLimit,
|
||||
ErrorOther,
|
||||
};
|
||||
|
||||
class SMatch {
|
||||
public:
|
||||
SMatch() :
|
||||
|
|
@ -76,13 +82,15 @@ class Regex {
|
|||
return (m_pc == NULL);
|
||||
}
|
||||
std::list<SMatch> searchAll(const std::string& s) const;
|
||||
bool searchOneMatch(const std::string& s, std::vector<SMatchCapture>& captures) const;
|
||||
bool searchGlobal(const std::string& s, std::vector<SMatchCapture>& captures) const;
|
||||
RegexResult searchOneMatch(const std::string& s, std::vector<SMatchCapture>& captures, unsigned long match_limit = 0) const;
|
||||
RegexResult searchGlobal(const std::string& s, std::vector<SMatchCapture>& captures, unsigned long match_limit = 0) const;
|
||||
int search(const std::string &s, SMatch *match) const;
|
||||
int search(const std::string &s) const;
|
||||
|
||||
const std::string pattern;
|
||||
private:
|
||||
RegexResult to_regex_result(int pcre_exec_result) const;
|
||||
|
||||
#if WITH_PCRE2
|
||||
pcre2_code *m_pc;
|
||||
int m_pcje;
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ void chomp(std::string *str) {
|
|||
}
|
||||
|
||||
|
||||
unsigned char x2c(unsigned char *what) {
|
||||
unsigned char x2c(const unsigned char *what) {
|
||||
unsigned char digit;
|
||||
|
||||
digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
|
||||
|
|
@ -239,7 +239,7 @@ unsigned char x2c(unsigned char *what) {
|
|||
/**
|
||||
* Converts a single hexadecimal digit into a decimal value.
|
||||
*/
|
||||
unsigned char xsingle2c(unsigned char *what) {
|
||||
unsigned char xsingle2c(const unsigned char *what) {
|
||||
unsigned char digit;
|
||||
|
||||
digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
|
||||
|
|
|
|||
|
|
@ -73,8 +73,8 @@ void replaceAll(std::string *str, const std::string& from,
|
|||
std::string removeWhiteSpacesIfNeeded(std::string a);
|
||||
std::string parserSanitizer(std::string a);
|
||||
|
||||
unsigned char x2c(unsigned char *what);
|
||||
unsigned char xsingle2c(unsigned char *what);
|
||||
unsigned char x2c(const unsigned char *what);
|
||||
unsigned char xsingle2c(const unsigned char *what);
|
||||
unsigned char *c2x(unsigned what, unsigned char *where);
|
||||
|
||||
} // namespace string
|
||||
|
|
|
|||
|
|
@ -106,8 +106,8 @@ class Global_DynamicElement : public Variable {
|
|||
t->m_rules->m_secWebAppId.m_value);
|
||||
}
|
||||
|
||||
static void storeOrUpdateFirst(Transaction *t, std::string var,
|
||||
std::string value) {
|
||||
static void storeOrUpdateFirst(Transaction *t, const std::string &var,
|
||||
const std::string &value) {
|
||||
t->m_collections.m_global_collection->storeOrUpdateFirst(
|
||||
var, t->m_collections.m_global_collection_key,
|
||||
t->m_rules->m_secWebAppId.m_value,
|
||||
|
|
|
|||
39
src/variables/msc_pcre_error.h
Normal file
39
src/variables/msc_pcre_error.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 - 2022 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <utility>
|
||||
|
||||
#ifndef SRC_VARIABLES_MSC_PCRE_ERROR_H_
|
||||
#define SRC_VARIABLES_MSC_PCRE_ERROR_H_
|
||||
|
||||
#include "src/variables/variable.h"
|
||||
|
||||
namespace modsecurity {
|
||||
|
||||
class Transaction;
|
||||
namespace variables {
|
||||
|
||||
|
||||
DEFINE_VARIABLE(MscPcreError, MSC_PCRE_ERROR, m_variableMscPcreError)
|
||||
|
||||
|
||||
} // namespace variables
|
||||
} // namespace modsecurity
|
||||
|
||||
#endif // SRC_VARIABLES_MSC_PCRE_ERROR_H_
|
||||
39
src/variables/msc_pcre_limits_exceeded.h
Normal file
39
src/variables/msc_pcre_limits_exceeded.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 - 2022 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* If any of the files related to licensing are missing or if you have any
|
||||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <utility>
|
||||
|
||||
#ifndef SRC_VARIABLES_MSC_PCRE_LIMITS_EXCEEDED_H_
|
||||
#define SRC_VARIABLES_MSC_PCRE_LIMITS_EXCEEDED_H_
|
||||
|
||||
#include "src/variables/variable.h"
|
||||
|
||||
namespace modsecurity {
|
||||
|
||||
class Transaction;
|
||||
namespace variables {
|
||||
|
||||
|
||||
DEFINE_VARIABLE(MscPcreLimitsExceeded, MSC_PCRE_LIMITS_EXCEEDED, m_variableMscPcreLimitsExceeded)
|
||||
|
||||
|
||||
} // namespace variables
|
||||
} // namespace modsecurity
|
||||
|
||||
#endif // SRC_VARIABLES_MSC_PCRE_LIMITS_EXCEEDED_H_
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
* Copyright (c) 2015 - 2023 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||||
*
|
||||
* You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
|
|
@ -179,163 +179,201 @@ class VariableMonkeyResolution {
|
|||
static void stringMatchResolveMulti(Transaction *t,
|
||||
const std::string &variable,
|
||||
std::vector<const VariableValue *> *l) {
|
||||
size_t collection = variable.find(".");
|
||||
if (collection == std::string::npos) {
|
||||
collection = variable.find(":");
|
||||
size_t collection_delimiter_offset = variable.find(".");
|
||||
if (collection_delimiter_offset == std::string::npos) {
|
||||
collection_delimiter_offset = variable.find(":");
|
||||
}
|
||||
if (collection == std::string::npos) {
|
||||
if (comp(variable, "RESPONSE_CONTENT_TYPE")) {
|
||||
t->m_variableResponseContentType.evaluate(l);
|
||||
} else if (comp(variable, "ARGS_COMBINED_SIZE")) {
|
||||
t->m_variableARGScombinedSize.evaluate(l);
|
||||
} else if (comp(variable, "AUTH_TYPE")) {
|
||||
t->m_variableAuthType.evaluate(l);
|
||||
} else if (comp(variable, "FILES_COMBINED_SIZE")) {
|
||||
t->m_variableFilesCombinedSize.evaluate(l);
|
||||
} else if (comp(variable, "FULL_REQUEST")) {
|
||||
t->m_variableFullRequest.evaluate(l);
|
||||
} else if (comp(variable, "FULL_REQUEST_LENGTH")) {
|
||||
t->m_variableFullRequestLength.evaluate(l);
|
||||
} else if (comp(variable, "INBOUND_DATA_ERROR")) {
|
||||
t->m_variableInboundDataError.evaluate(l);
|
||||
} else if (comp(variable, "MATCHED_VAR")) {
|
||||
t->m_variableMatchedVar.evaluate(l);
|
||||
} else if (comp(variable, "MATCHED_VAR_NAME")) {
|
||||
t->m_variableMatchedVarName.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_CRLF_LF_LINES")) {
|
||||
t->m_variableMultipartCrlfLFLines.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_DATA_AFTER")) {
|
||||
t->m_variableMultipartDataAfter.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_FILE_LIMIT_EXCEEDED")) {
|
||||
t->m_variableMultipartFileLimitExceeded.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_STRICT_ERROR")) {
|
||||
t->m_variableMultipartStrictError.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_HEADER_FOLDING")) {
|
||||
t->m_variableMultipartHeaderFolding.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_INVALID_QUOTING")) {
|
||||
t->m_variableMultipartInvalidQuoting.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_INVALID_HEADER_FOLDING")) {
|
||||
t->m_variableMultipartInvalidHeaderFolding.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_UNMATCHED_BOUNDARY")) {
|
||||
t->m_variableMultipartUnmatchedBoundary.evaluate(l);
|
||||
} else if (comp(variable, "OUTBOUND_DATA_ERROR")) {
|
||||
t->m_variableOutboundDataError.evaluate(l);
|
||||
} else if (comp(variable, "PATH_INFO")) {
|
||||
t->m_variablePathInfo.evaluate(l);
|
||||
} else if (comp(variable, "QUERY_STRING")) {
|
||||
t->m_variableQueryString.evaluate(l);
|
||||
} else if (comp(variable, "REMOTE_ADDR")) {
|
||||
t->m_variableRemoteAddr.evaluate(l);
|
||||
} else if (comp(variable, "REMOTE_HOST")) {
|
||||
t->m_variableRemoteHost.evaluate(l);
|
||||
} else if (comp(variable, "REMOTE_PORT")) {
|
||||
t->m_variableRemotePort.evaluate(l);
|
||||
} else if (comp(variable, "REQBODY_ERROR")) {
|
||||
t->m_variableReqbodyError.evaluate(l);
|
||||
} else if (comp(variable, "REQBODY_ERROR_MSG")) {
|
||||
t->m_variableReqbodyErrorMsg.evaluate(l);
|
||||
} else if (comp(variable, "REQBODY_PROCESSOR_ERROR_MSG")) {
|
||||
t->m_variableReqbodyProcessorErrorMsg.evaluate(l);
|
||||
} else if (comp(variable, "REQBODY_PROCESSOR_ERROR")) {
|
||||
t->m_variableReqbodyProcessorError.evaluate(l);
|
||||
} else if (comp(variable, "REQBODY_PROCESSOR")) {
|
||||
t->m_variableReqbodyProcessor.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_BASENAME")) {
|
||||
t->m_variableRequestBasename.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_BODY")) {
|
||||
t->m_variableRequestBody.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_BODY_LENGTH")) {
|
||||
t->m_variableRequestBodyLength.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_FILENAME")) {
|
||||
t->m_variableRequestFilename.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_LINE")) {
|
||||
t->m_variableRequestLine.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_METHOD")) {
|
||||
t->m_variableRequestMethod.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_PROTOCOL")) {
|
||||
t->m_variableRequestProtocol.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_URI")) {
|
||||
t->m_variableRequestURI.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_URI_RAW")) {
|
||||
t->m_variableRequestURIRaw.evaluate(l);
|
||||
} else if (comp(variable, "RESOURCE")) {
|
||||
t->m_variableResource.evaluate(l);
|
||||
} else if (comp(variable, "RESPONSE_BODY")) {
|
||||
t->m_variableResponseBody.evaluate(l);
|
||||
} else if (comp(variable, "RESPONSE_CONTENT_LENGTH")) {
|
||||
t->m_variableResponseContentLength.evaluate(l);
|
||||
} else if (comp(variable, "RESPONSE_PROTOCOL")) {
|
||||
t->m_variableResponseProtocol.evaluate(l);
|
||||
} else if (comp(variable, "RESPONSE_STATUS")) {
|
||||
t->m_variableResponseStatus.evaluate(l);
|
||||
} else if (comp(variable, "SERVER_ADDR")) {
|
||||
t->m_variableServerAddr.evaluate(l);
|
||||
} else if (comp(variable, "SERVER_NAME")) {
|
||||
t->m_variableServerName.evaluate(l);
|
||||
} else if (comp(variable, "SERVER_PORT")) {
|
||||
t->m_variableServerPort.evaluate(l);
|
||||
} else if (comp(variable, "SESSIONID")) {
|
||||
t->m_variableSessionID.evaluate(l);
|
||||
} else if (comp(variable, "UNIQUE_ID")) {
|
||||
t->m_variableUniqueID.evaluate(l);
|
||||
} else if (comp(variable, "URLENCODED_ERROR")) {
|
||||
t->m_variableUrlEncodedError.evaluate(l);
|
||||
} else if (comp(variable, "USERID")) {
|
||||
t->m_variableUserID.evaluate(l);
|
||||
} else {
|
||||
throw std::invalid_argument("Variable not found.");
|
||||
}
|
||||
std::string col; // collection name excluding individual variable specification
|
||||
std::string var; // variable within the collection
|
||||
if (collection_delimiter_offset == std::string::npos) {
|
||||
col = variable;
|
||||
} else {
|
||||
std::string col = std::string(variable, 0, collection);
|
||||
std::string var = std::string(variable, collection + 1,
|
||||
variable.length() - (collection + 1));
|
||||
if (comp(col, "ARGS")) {
|
||||
t->m_variableArgs.resolve(var, l);
|
||||
} else if (comp(variable, "ARGS_NAMES")) {
|
||||
t->m_variableArgsNames.resolve(var, l);
|
||||
} else if (comp(variable, "ARGS_GET_NAMES")) {
|
||||
t->m_variableArgsGetNames.resolve(var, l);
|
||||
} else if (comp(variable, "ARGS_POST_NAMES")) {
|
||||
t->m_variableArgsPostNames.resolve(var, l);
|
||||
} else if (comp(col, "ARGS_GET")) {
|
||||
t->m_variableArgsGet.resolve(var, l);
|
||||
} else if (comp(col, "ARGS_POST")) {
|
||||
t->m_variableArgsPost.resolve(var, l);
|
||||
} else if (comp(col, "FILES_SIZES")) {
|
||||
t->m_variableFilesSizes.resolve(var, l);
|
||||
} else if (comp(col, "FILES_NAMES")) {
|
||||
t->m_variableFilesNames.resolve(var, l);
|
||||
} else if (comp(col, "FILES_TMP_CONTENT")) {
|
||||
t->m_variableFilesTmpContent.resolve(var, l);
|
||||
} else if (comp(col, "MULTIPART_FILENAME")) {
|
||||
t->m_variableMultipartFileName.resolve(var, l);
|
||||
} else if (comp(col, "MULTIPART_NAME")) {
|
||||
t->m_variableMultipartName.resolve(var, l);
|
||||
} else if (comp(col, "MATCHED_VARS_NAMES")) {
|
||||
t->m_variableMatchedVarsNames.resolve(var, l);
|
||||
} else if (comp(col, "MATCHED_VARS")) {
|
||||
t->m_variableMatchedVars.resolve(var, l);
|
||||
} else if (comp(col, "FILES")) {
|
||||
t->m_variableFiles.resolve(var, l);
|
||||
} else if (comp(col, "REQUEST_COOKIES")) {
|
||||
t->m_variableRequestCookies.resolve(var, l);
|
||||
} else if (comp(col, "REQUEST_HEADERS")) {
|
||||
t->m_variableRequestHeaders.resolve(var, l);
|
||||
} else if (comp(variable, "REQUEST_HEADERS_NAMES")) {
|
||||
t->m_variableRequestHeadersNames.resolve(var, l);
|
||||
} else if (comp(col, "RESPONSE_HEADERS")) {
|
||||
t->m_variableResponseHeaders.resolve(var, l);
|
||||
} else if (comp(variable, "RESPONSE_HEADERS_NAMES")) {
|
||||
t->m_variableResponseHeadersNames.resolve(var, l);
|
||||
} else if (comp(col, "GEO")) {
|
||||
t->m_variableGeo.resolve(var, l);
|
||||
} else if (comp(col, "REQUEST_COOKIES_NAMES")) {
|
||||
t->m_variableRequestCookiesNames.resolve(var, l);
|
||||
} else if (comp(col, "FILES_TMPNAMES")) {
|
||||
t->m_variableFilesTmpNames.resolve(var, l);
|
||||
col = std::string(variable, 0, collection_delimiter_offset);
|
||||
var = std::string(variable, collection_delimiter_offset + 1,
|
||||
variable.length() - (collection_delimiter_offset + 1));
|
||||
}
|
||||
|
||||
// First check if the request is for a collection of type AnchoredSetVariable
|
||||
AnchoredSetVariable* anchoredSetVariable = NULL;
|
||||
if (comp(col, "ARGS")) {
|
||||
anchoredSetVariable = &t->m_variableArgs;
|
||||
} else if (comp(col, "ARGS_GET")) {
|
||||
anchoredSetVariable = &t->m_variableArgsGet;
|
||||
} else if (comp(col, "ARGS_POST")) {
|
||||
anchoredSetVariable = &t->m_variableArgsPost;
|
||||
} else if (comp(col, "FILES_SIZES")) {
|
||||
anchoredSetVariable = &t->m_variableFilesSizes;
|
||||
} else if (comp(col, "FILES_NAMES")) {
|
||||
anchoredSetVariable = &t->m_variableFilesNames;
|
||||
} else if (comp(col, "FILES_TMP_CONTENT")) {
|
||||
anchoredSetVariable = &t->m_variableFilesTmpContent;
|
||||
} else if (comp(col, "MULTIPART_FILENAME")) {
|
||||
anchoredSetVariable = &t->m_variableMultipartFileName;
|
||||
} else if (comp(col, "MULTIPART_NAME")) {
|
||||
anchoredSetVariable = &t->m_variableMultipartName;
|
||||
} else if (comp(col, "MATCHED_VARS_NAMES")) {
|
||||
anchoredSetVariable = &t->m_variableMatchedVarsNames;
|
||||
} else if (comp(col, "MATCHED_VARS")) {
|
||||
anchoredSetVariable = &t->m_variableMatchedVars;
|
||||
} else if (comp(col, "FILES")) {
|
||||
anchoredSetVariable = &t->m_variableFiles;
|
||||
} else if (comp(col, "REQUEST_COOKIES")) {
|
||||
anchoredSetVariable = &t->m_variableRequestCookies;
|
||||
} else if (comp(col, "REQUEST_HEADERS")) {
|
||||
anchoredSetVariable = &t->m_variableRequestHeaders;
|
||||
} else if (comp(variable, "REQUEST_HEADERS_NAMES")) {
|
||||
anchoredSetVariable = &t->m_variableRequestHeadersNames;
|
||||
} else if (comp(col, "RESPONSE_HEADERS")) {
|
||||
anchoredSetVariable = &t->m_variableResponseHeaders;
|
||||
} else if (comp(variable, "RESPONSE_HEADERS_NAMES")) {
|
||||
anchoredSetVariable = &t->m_variableResponseHeadersNames;
|
||||
} else if (comp(col, "GEO")) {
|
||||
anchoredSetVariable = &t->m_variableGeo;
|
||||
} else if (comp(col, "REQUEST_COOKIES_NAMES")) {
|
||||
anchoredSetVariable = &t->m_variableRequestCookiesNames;
|
||||
} else if (comp(col, "MULTIPART_PART_HEADERS")) {
|
||||
anchoredSetVariable = &t->m_variableMultipartPartHeaders;
|
||||
} else if (comp(col, "FILES_TMPNAMES")) {
|
||||
anchoredSetVariable = &t->m_variableFilesTmpNames;
|
||||
}
|
||||
if (anchoredSetVariable != NULL) {
|
||||
if (collection_delimiter_offset == std::string::npos) {
|
||||
anchoredSetVariable->resolve(l);
|
||||
} else {
|
||||
throw std::invalid_argument("Variable not found.");
|
||||
anchoredSetVariable->resolve(var, l);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Next check for collection of type AnchoredSetVariableTranslationProxy
|
||||
AnchoredSetVariableTranslationProxy* anchoredSetVariableTranslationProxy = NULL;
|
||||
if (comp(col, "ARGS_NAMES")) {
|
||||
anchoredSetVariableTranslationProxy = &t->m_variableArgsNames;
|
||||
} else if (comp(col, "ARGS_GET_NAMES")) {
|
||||
anchoredSetVariableTranslationProxy = &t->m_variableArgsGetNames;
|
||||
} else if (comp(col, "ARGS_POST_NAMES")) {
|
||||
anchoredSetVariableTranslationProxy = &t->m_variableArgsPostNames;
|
||||
}
|
||||
if (anchoredSetVariableTranslationProxy != NULL) {
|
||||
if (collection_delimiter_offset == std::string::npos) {
|
||||
anchoredSetVariableTranslationProxy->resolve(l);
|
||||
} else {
|
||||
anchoredSetVariableTranslationProxy->resolve(var, l);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// It could still be a non-collection variable, but in that case
|
||||
// there should not be a request for a variable-within-a-collection
|
||||
if (collection_delimiter_offset != std::string::npos) {
|
||||
throw std::invalid_argument("Variable not found.");
|
||||
}
|
||||
|
||||
if (comp(variable, "RESPONSE_CONTENT_TYPE")) {
|
||||
t->m_variableResponseContentType.evaluate(l);
|
||||
} else if (comp(variable, "ARGS_COMBINED_SIZE")) {
|
||||
t->m_variableARGScombinedSize.evaluate(l);
|
||||
} else if (comp(variable, "AUTH_TYPE")) {
|
||||
t->m_variableAuthType.evaluate(l);
|
||||
} else if (comp(variable, "FILES_COMBINED_SIZE")) {
|
||||
t->m_variableFilesCombinedSize.evaluate(l);
|
||||
} else if (comp(variable, "FULL_REQUEST")) {
|
||||
t->m_variableFullRequest.evaluate(l);
|
||||
} else if (comp(variable, "FULL_REQUEST_LENGTH")) {
|
||||
t->m_variableFullRequestLength.evaluate(l);
|
||||
} else if (comp(variable, "INBOUND_DATA_ERROR")) {
|
||||
t->m_variableInboundDataError.evaluate(l);
|
||||
} else if (comp(variable, "MATCHED_VAR")) {
|
||||
t->m_variableMatchedVar.evaluate(l);
|
||||
} else if (comp(variable, "MATCHED_VAR_NAME")) {
|
||||
t->m_variableMatchedVarName.evaluate(l);
|
||||
} else if (comp(variable, "MSC_PCRE_ERROR")) {
|
||||
t->m_variableMscPcreError.evaluate(l);
|
||||
} else if (comp(variable, "MSC_PCRE_LIMITS_EXCEEDED")) {
|
||||
t->m_variableMscPcreLimitsExceeded.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_CRLF_LF_LINES")) {
|
||||
t->m_variableMultipartCrlfLFLines.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_DATA_AFTER")) {
|
||||
t->m_variableMultipartDataAfter.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_FILE_LIMIT_EXCEEDED")) {
|
||||
t->m_variableMultipartFileLimitExceeded.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_STRICT_ERROR")) {
|
||||
t->m_variableMultipartStrictError.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_HEADER_FOLDING")) {
|
||||
t->m_variableMultipartHeaderFolding.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_INVALID_QUOTING")) {
|
||||
t->m_variableMultipartInvalidQuoting.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_INVALID_HEADER_FOLDING")) {
|
||||
t->m_variableMultipartInvalidHeaderFolding.evaluate(l);
|
||||
} else if (comp(variable, "MULTIPART_UNMATCHED_BOUNDARY")) {
|
||||
t->m_variableMultipartUnmatchedBoundary.evaluate(l);
|
||||
} else if (comp(variable, "OUTBOUND_DATA_ERROR")) {
|
||||
t->m_variableOutboundDataError.evaluate(l);
|
||||
} else if (comp(variable, "PATH_INFO")) {
|
||||
t->m_variablePathInfo.evaluate(l);
|
||||
} else if (comp(variable, "QUERY_STRING")) {
|
||||
t->m_variableQueryString.evaluate(l);
|
||||
} else if (comp(variable, "REMOTE_ADDR")) {
|
||||
t->m_variableRemoteAddr.evaluate(l);
|
||||
} else if (comp(variable, "REMOTE_HOST")) {
|
||||
t->m_variableRemoteHost.evaluate(l);
|
||||
} else if (comp(variable, "REMOTE_PORT")) {
|
||||
t->m_variableRemotePort.evaluate(l);
|
||||
} else if (comp(variable, "REQBODY_ERROR")) {
|
||||
t->m_variableReqbodyError.evaluate(l);
|
||||
} else if (comp(variable, "REQBODY_ERROR_MSG")) {
|
||||
t->m_variableReqbodyErrorMsg.evaluate(l);
|
||||
} else if (comp(variable, "REQBODY_PROCESSOR_ERROR_MSG")) {
|
||||
t->m_variableReqbodyProcessorErrorMsg.evaluate(l);
|
||||
} else if (comp(variable, "REQBODY_PROCESSOR_ERROR")) {
|
||||
t->m_variableReqbodyProcessorError.evaluate(l);
|
||||
} else if (comp(variable, "REQBODY_PROCESSOR")) {
|
||||
t->m_variableReqbodyProcessor.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_BASENAME")) {
|
||||
t->m_variableRequestBasename.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_BODY")) {
|
||||
t->m_variableRequestBody.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_BODY_LENGTH")) {
|
||||
t->m_variableRequestBodyLength.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_FILENAME")) {
|
||||
t->m_variableRequestFilename.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_LINE")) {
|
||||
t->m_variableRequestLine.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_METHOD")) {
|
||||
t->m_variableRequestMethod.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_PROTOCOL")) {
|
||||
t->m_variableRequestProtocol.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_URI")) {
|
||||
t->m_variableRequestURI.evaluate(l);
|
||||
} else if (comp(variable, "REQUEST_URI_RAW")) {
|
||||
t->m_variableRequestURIRaw.evaluate(l);
|
||||
} else if (comp(variable, "RESOURCE")) {
|
||||
t->m_variableResource.evaluate(l);
|
||||
} else if (comp(variable, "RESPONSE_BODY")) {
|
||||
t->m_variableResponseBody.evaluate(l);
|
||||
} else if (comp(variable, "RESPONSE_CONTENT_LENGTH")) {
|
||||
t->m_variableResponseContentLength.evaluate(l);
|
||||
} else if (comp(variable, "RESPONSE_PROTOCOL")) {
|
||||
t->m_variableResponseProtocol.evaluate(l);
|
||||
} else if (comp(variable, "RESPONSE_STATUS")) {
|
||||
t->m_variableResponseStatus.evaluate(l);
|
||||
} else if (comp(variable, "SERVER_ADDR")) {
|
||||
t->m_variableServerAddr.evaluate(l);
|
||||
} else if (comp(variable, "SERVER_NAME")) {
|
||||
t->m_variableServerName.evaluate(l);
|
||||
} else if (comp(variable, "SERVER_PORT")) {
|
||||
t->m_variableServerPort.evaluate(l);
|
||||
} else if (comp(variable, "SESSIONID")) {
|
||||
t->m_variableSessionID.evaluate(l);
|
||||
} else if (comp(variable, "UNIQUE_ID")) {
|
||||
t->m_variableUniqueID.evaluate(l);
|
||||
} else if (comp(variable, "URLENCODED_ERROR")) {
|
||||
t->m_variableUrlEncodedError.evaluate(l);
|
||||
} else if (comp(variable, "USERID")) {
|
||||
t->m_variableUserID.evaluate(l);
|
||||
} else {
|
||||
throw std::invalid_argument("Variable not found.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -365,6 +403,10 @@ class VariableMonkeyResolution {
|
|||
vv = t->m_variableMatchedVar.resolveFirst();
|
||||
} else if (comp(variable, "MATCHED_VAR_NAME")) {
|
||||
vv = t->m_variableMatchedVarName.resolveFirst();
|
||||
} else if (comp(variable, "MSC_PCRE_ERROR")) {
|
||||
vv = t->m_variableMscPcreError.resolveFirst();
|
||||
} else if (comp(variable, "MSC_PCRE_LIMITS_EXCEEDED")) {
|
||||
vv = t->m_variableMscPcreLimitsExceeded.resolveFirst();
|
||||
} else if (comp(variable, "MULTIPART_CRLF_LF_LINES")) {
|
||||
vv = t->m_variableMultipartCrlfLFLines.resolveFirst();
|
||||
} else if (comp(variable, "MULTIPART_DATA_AFTER")) {
|
||||
|
|
@ -513,6 +555,8 @@ class VariableMonkeyResolution {
|
|||
vv = t->m_variableRequestCookiesNames.resolveFirst(var);
|
||||
} else if (comp(col, "FILES_TMPNAMES")) {
|
||||
vv = t->m_variableFilesTmpNames.resolveFirst(var);
|
||||
} else if (comp(col, "MULTIPART_PART_HEADERS")) {
|
||||
vv = t->m_variableMultipartPartHeaders.resolveFirst(var);
|
||||
} else if (comp(col, "TX")) {
|
||||
vv = t->m_collections.m_tx_collection->resolveFirst(var);
|
||||
} else if (comp(col, "RESOURCE")) {
|
||||
|
|
@ -608,7 +652,7 @@ class Variables : public std::vector<Variable *> {
|
|||
public:
|
||||
bool contains(Variable *v) {
|
||||
return std::find_if(begin(), end(),
|
||||
[v](Variable *m) -> bool { return *v == *m; }) != end();
|
||||
[v](const Variable *m) -> bool { return *v == *m; }) != end();
|
||||
};
|
||||
bool contains(const VariableValue *v) {
|
||||
return std::find_if(begin(), end(),
|
||||
|
|
|
|||
|
|
@ -53,14 +53,11 @@ duplicateBranch:src/request_body_processor/multipart.cc:93
|
|||
danglingTempReference:src/modsecurity.cc:206
|
||||
knownConditionTrueFalse:src/operators/validate_url_encoding.cc:77
|
||||
knownConditionTrueFalse:src/operators/verify_svnr.cc:87
|
||||
rethrowNoCurrentException:headers/modsecurity/transaction.h:309
|
||||
rethrowNoCurrentException:headers/modsecurity/transaction.h:313
|
||||
rethrowNoCurrentException:src/rule_with_actions.cc:127
|
||||
ctunullpointer:src/rule_with_actions.cc:241
|
||||
ctunullpointer:src/rule_with_actions.cc:244
|
||||
ctunullpointer:src/rule_with_operator.cc:135
|
||||
ctunullpointer:src/rule_with_operator.cc:95
|
||||
passedByValue:src/variables/global.h:109
|
||||
passedByValue:src/variables/global.h:110
|
||||
passedByValue:src/parser/driver.cc:46
|
||||
passedByValue:test/common/modsecurity_test.cc:49
|
||||
passedByValue:test/common/modsecurity_test.cc:98
|
||||
unreadVariable:src/rule_with_operator.cc:219
|
||||
|
|
@ -68,28 +65,33 @@ unreadVariable:src/rule_with_operator.cc:219
|
|||
uninitvar:src/operators/verify_cpf.cc:77
|
||||
uninitvar:src/operators/verify_svnr.cc:67
|
||||
|
||||
functionConst:src/collection/backend/lmdb.h:86
|
||||
unusedLabel:src/collection/backend/lmdb.cc:297
|
||||
|
||||
variableScope:src/operators/rx.cc
|
||||
variableScope:src/operators/rx_global.cc
|
||||
|
||||
noExplicitConstructor:seclang-parser.hh
|
||||
constParameter:seclang-parser.hh
|
||||
accessMoved:seclang-parser.hh
|
||||
returnTempReference:seclang-parser.hh
|
||||
|
||||
unreadVariable:src/operators/rx.cc
|
||||
unreadVariable:src/operators/rx_global.cc
|
||||
|
||||
|
||||
unusedFunction
|
||||
missingIncludeSystem
|
||||
useStlAlgorithm
|
||||
preprocessorErrorDirective
|
||||
funcArgNamesDifferent
|
||||
unmatchedSuppression
|
||||
missingInclude
|
||||
|
||||
purgedConfiguration
|
||||
|
||||
constParameter
|
||||
|
||||
nullPointerRedundantCheck
|
||||
knownConditionTrueFalse
|
||||
cstyleCast
|
||||
functionStatic
|
||||
variableScope
|
||||
shadowFunction
|
||||
|
||||
constVariable
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
127.0.0.1
|
||||
|
||||
# Comment line
|
||||
10.10.10.1
|
||||
::1
|
||||
|
|
|
|||
13
test/test-cases/data/match-getvars-args.lua
Normal file
13
test/test-cases/data/match-getvars-args.lua
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
function main()
|
||||
local d = m.getvars("ARGS");
|
||||
local size = #d;
|
||||
m.log(9,"ARGS count read =" .. tostring(size));
|
||||
|
||||
ret = nil
|
||||
|
||||
if ( #d == 2 ) then
|
||||
return nil
|
||||
end
|
||||
|
||||
return "Unexpected result"
|
||||
end
|
||||
|
|
@ -253,14 +253,14 @@
|
|||
"body": ""
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "\\[msg \"testmsg\"\\]",
|
||||
"audit_log": "\\[msg \"testmsg\"\\] \\[data \"testdata\"\\] \\[severity \"7\"\\] \\[ver \"\"\\] \\[maturity \"0\"\\] \\[accuracy \"0\"\\] \\[tag \"testtag1\"\\] \\[tag \"testtag2\"\\]",
|
||||
"error_log": "",
|
||||
"http_code": 403
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecDefaultAction \"phase:1,nolog,auditlog,deny,status:403\"",
|
||||
"SecRule ARGS \"@contains test2\" \"id:1557,phase:1,multiMatch,block,log,t:none,t:urlDecode,t:lowercase,msg:'testmsg'\"",
|
||||
"SecRule ARGS \"@contains test2\" \"id:1557,phase:1,multiMatch,block,log,t:none,t:urlDecode,t:lowercase,msg:'testmsg',logdata:'testdata',severity:'DEBUG',tag:'testtag1',tag:'testtag2'\"",
|
||||
"SecAuditEngine RelevantOnly",
|
||||
"SecAuditLogParts ABCFHZ",
|
||||
"SecAuditLog /tmp/test/modsec_audit_multimatch_1.log",
|
||||
|
|
@ -302,14 +302,14 @@
|
|||
"body": ""
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "\\[msg \"tstmsg\"\\]",
|
||||
"audit_log": "\\[msg \"testmsg\"\\] \\[data \"testdata\"\\] \\[severity \"7\"\\] \\[ver \"\"\\] \\[maturity \"0\"\\] \\[accuracy \"0\"\\] \\[tag \"testtag1\"\\] \\[tag \"testtag2\"\\]",
|
||||
"error_log": "",
|
||||
"http_code": 403
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecDefaultAction \"phase:1,nolog,auditlog,deny,status:403\"",
|
||||
"SecRule ARGS \"@streq tEst2\" \"id:1558,phase:1,multiMatch,block,log,t:none,t:trim,t:lowercase,msg:'tstmsg'\"",
|
||||
"SecRule ARGS \"@streq tEst2\" \"id:1558,phase:1,multiMatch,block,log,t:none,t:trim,t:lowercase,msg:'testmsg',logdata:'testdata',severity:'DEBUG',tag:'testtag1',tag:'testtag2'\"",
|
||||
"SecAuditEngine RelevantOnly",
|
||||
"SecAuditLogParts ABCFHZ",
|
||||
"SecAuditLog /tmp/test/modsec_audit_multimatch_2.log",
|
||||
|
|
@ -318,5 +318,105 @@
|
|||
"SecAuditLogType Serial",
|
||||
"SecAuditLogRelevantStatus \"^(?:5|4(?!04))\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
"version_max": 0,
|
||||
"title": "auditlog : rule chain, multiMatch data, match after last transform",
|
||||
"client": {
|
||||
"ip": "200.249.12.31",
|
||||
"port": 2313
|
||||
},
|
||||
"server": {
|
||||
"ip": "200.249.12.31",
|
||||
"port": 80
|
||||
},
|
||||
"request": {
|
||||
"headers": {
|
||||
"Host": "www.modsecurity.org",
|
||||
"User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)",
|
||||
"Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8",
|
||||
"Accept-Language": "en-us,en;q=0.5",
|
||||
"Accept-Encoding": "gzip,deflate",
|
||||
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
|
||||
"Keep-Alive": "300",
|
||||
"Connection": "keep-alive",
|
||||
"Pragma": "no-cache",
|
||||
"Cache-Control": "no-cache"
|
||||
},
|
||||
"uri": "\/test.pl?param1=test¶m2=tEst2",
|
||||
"method": "GET",
|
||||
"http_version": 1.1,
|
||||
"body": ""
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "\\[msg \"testmsg\"\\] \\[data \"testdata\"\\] \\[severity \"7\"\\] \\[ver \"\"\\] \\[maturity \"0\"\\] \\[accuracy \"0\"\\] \\[tag \"testtag1\"\\] \\[tag \"testtag2\"\\]",
|
||||
"error_log": "",
|
||||
"http_code": 403
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecDefaultAction \"phase:1,nolog,auditlog,deny,status:403\"",
|
||||
"SecRule ARGS \"@contains test2\" \"id:1559,phase:1,multiMatch,block,log,t:none,t:urlDecode,t:lowercase,msg:'testmsg',logdata:'testdata',severity:'DEBUG',tag:'testtag1',tag:'testtag2',chain\"",
|
||||
"SecRule REQUEST_METHOD \"@streq GET\" \"t:none\"",
|
||||
"SecAuditEngine RelevantOnly",
|
||||
"SecAuditLogParts ABCFHZ",
|
||||
"SecAuditLog /tmp/test/modsec_audit_multimatch_3.log",
|
||||
"SecAuditLogDirMode 0766",
|
||||
"SecAuditLogFileMode 0666",
|
||||
"SecAuditLogType Serial",
|
||||
"SecAuditLogRelevantStatus \"^(?:5|4(?!04))\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
"version_max": 0,
|
||||
"title": "auditlog : rule chain, multiMatch data, match only after intermediate transform",
|
||||
"client": {
|
||||
"ip": "200.249.12.31",
|
||||
"port": 2313
|
||||
},
|
||||
"server": {
|
||||
"ip": "200.249.12.31",
|
||||
"port": 80
|
||||
},
|
||||
"request": {
|
||||
"headers": {
|
||||
"Host": "www.modsecurity.org",
|
||||
"User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)",
|
||||
"Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8",
|
||||
"Accept-Language": "en-us,en;q=0.5",
|
||||
"Accept-Encoding": "gzip,deflate",
|
||||
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
|
||||
"Keep-Alive": "300",
|
||||
"Connection": "keep-alive",
|
||||
"Pragma": "no-cache",
|
||||
"Cache-Control": "no-cache"
|
||||
},
|
||||
"uri": "\/test.pl?param1=test¶m2=%20tEst2",
|
||||
"method": "GET",
|
||||
"http_version": 1.1,
|
||||
"body": ""
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "\\[msg \"testmsg\"\\] \\[data \"testdata\"\\] \\[severity \"7\"\\] \\[ver \"\"\\] \\[maturity \"0\"\\] \\[accuracy \"0\"\\] \\[tag \"testtag1\"\\] \\[tag \"testtag2\"\\]",
|
||||
"error_log": "",
|
||||
"http_code": 403
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecDefaultAction \"phase:1,nolog,auditlog,deny,status:403\"",
|
||||
"SecRule ARGS \"@streq tEst2\" \"id:1560,phase:1,multiMatch,block,log,t:none,t:trim,t:lowercase,msg:'testmsg',logdata:'testdata',severity:'DEBUG',tag:'testtag1',tag:'testtag2',chain\"",
|
||||
"SecRule REQUEST_METHOD \"@streq GET\" \"t:none\"",
|
||||
"SecAuditEngine RelevantOnly",
|
||||
"SecAuditLogParts ABCFHZ",
|
||||
"SecAuditLog /tmp/test/modsec_audit_multimatch_4.log",
|
||||
"SecAuditLogDirMode 0766",
|
||||
"SecAuditLogFileMode 0666",
|
||||
"SecAuditLogType Serial",
|
||||
"SecAuditLogRelevantStatus \"^(?:5|4(?!04))\""
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing LUA :: m.set TX (1/6)",
|
||||
"title":"Testing LUA :: m.set TX (1/7)",
|
||||
"resource":"lua",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
|
|
@ -44,7 +44,7 @@
|
|||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing LUA :: m.set IP (2/6)",
|
||||
"title":"Testing LUA :: m.set IP (2/7)",
|
||||
"resource":"lua",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
|
|
@ -86,7 +86,7 @@
|
|||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing LUA :: m.set GLOBAL (3/6)",
|
||||
"title":"Testing LUA :: m.set GLOBAL (3/7)",
|
||||
"resource":"lua",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
|
|
@ -128,7 +128,7 @@
|
|||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing LUA :: m.set RESOURCE (4/6)",
|
||||
"title":"Testing LUA :: m.set RESOURCE (4/7)",
|
||||
"resource":"lua",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
|
|
@ -170,7 +170,7 @@
|
|||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing LUA :: m.set SESSION (5/6)",
|
||||
"title":"Testing LUA :: m.set SESSION (5/7)",
|
||||
"resource":"lua",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
|
|
@ -212,7 +212,7 @@
|
|||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing LUA :: m.set USER (6/6)",
|
||||
"title":"Testing LUA :: m.set USER (6/7)",
|
||||
"resource":"lua",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
|
|
@ -250,5 +250,43 @@
|
|||
"SecRuleScript test-cases/data/setvar.lua \"id:2,pass\"",
|
||||
"SecRule USER.lua_set_var \"@contains 2\" \"id:3,t:none\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing LUA :: m.getvars ARGS (8/8)",
|
||||
"resource":"lua",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"My sweet little browser",
|
||||
"Accept":"*/*",
|
||||
"Content-Length": "0"
|
||||
},
|
||||
"uri":"/whee?parm1=a&parm2=b",
|
||||
"method":"GET",
|
||||
"body": [ ]
|
||||
},
|
||||
"response":{
|
||||
"headers":{},
|
||||
"body":[
|
||||
"no need."
|
||||
]
|
||||
},
|
||||
"expected":{
|
||||
"http_code": 200
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRuleScript test-cases/data/match-getvars-args.lua \"id:2,phase:2,deny,status:403\""
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Include (1/7)",
|
||||
"title":"Include (1/8)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Include (2/7)",
|
||||
"title":"Include (2/8)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
|
|
@ -82,7 +82,7 @@
|
|||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Include (3/7)",
|
||||
"title":"Include (3/8)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
|
|
@ -122,7 +122,7 @@
|
|||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Include (4/7)",
|
||||
"title":"Include (4/8)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
|
|
@ -162,7 +162,7 @@
|
|||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Include (5/7)",
|
||||
"title":"Include (5/8)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
|
|
@ -203,7 +203,7 @@
|
|||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Include (6/7)",
|
||||
"title":"Include (6/8)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
|
|
@ -243,7 +243,7 @@
|
|||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Include (7/7)",
|
||||
"title":"Include (7/8)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
|
|
@ -279,5 +279,45 @@
|
|||
"Include test-cases/data/conasdffig_example2.txt",
|
||||
"SecRule ARGS \"@contains test\" \"id:9,pass,t:trim\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Include (8/8) -- quoted with wildcard",
|
||||
"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":"*/*"
|
||||
},
|
||||
"uri":"/?key=value&key=other_value",
|
||||
"method":"GET"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"body":[
|
||||
"no need."
|
||||
]
|
||||
},
|
||||
"expected":{
|
||||
"debug_log":"Executing operator \"Contains\" with param \"config_example2\" against ARGS."
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"Include \"test-cases/data/config_ex*ple2.txt\"",
|
||||
"SecRule ARGS \"@contains test\" \"id:9,pass,t:trim\""
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -127,5 +127,140 @@
|
|||
"SecRuleEngine On",
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"@rx a(b\" \"id:1,phase:2,pass,t:trim,block\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Operator :: @rx with PCRE error",
|
||||
"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": "27",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
"uri":"/?rxtest=wwwwwwwwwwwwwwwwwwwwwowwwwwwwwwww",
|
||||
"method":"HEAD",
|
||||
"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"
|
||||
},
|
||||
"body":[
|
||||
"no need."
|
||||
]
|
||||
},
|
||||
"expected":{
|
||||
"debug_log":"rx: regex error 'MATCH_LIMIT' for pattern",
|
||||
"error_log":"Matched \"Operator `StrEq' with parameter `1' against variable `MSC_PCRE_ERROR'"
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecPcreMatchLimit 2",
|
||||
"SecRule ARGS:rxtest \"@rx (w+)+$\" \"id:1,phase:1,pass,t:trim,block\"",
|
||||
"SecRule MSC_PCRE_ERROR \"@streq 1\" \"id:2,phase:1,pass,t:trim,block\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Operator :: @rx with PCRE match limits exceeded",
|
||||
"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": "27",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
"uri":"/?rxtest=wwwwwwwwwwwwwwwwwwwwwowwwwwwwwwww",
|
||||
"method":"HEAD",
|
||||
"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"
|
||||
},
|
||||
"body":[
|
||||
"no need."
|
||||
]
|
||||
},
|
||||
"expected":{
|
||||
"debug_log":"rx: regex error 'MATCH_LIMIT' for pattern",
|
||||
"error_log":"Matched \"Operator `StrEq' with parameter `1' against variable `MSC_PCRE_LIMITS_EXCEEDED'"
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecPcreMatchLimit 2",
|
||||
"SecRule ARGS:rxtest \"@rx (w+)+$\" \"id:1,phase:1,pass,t:trim,block\"",
|
||||
"SecRule MSC_PCRE_LIMITS_EXCEEDED \"@streq 1\" \"id:2,phase:1,pass,t:trim,block\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Operator :: @rx with PCRE match limits exceeded",
|
||||
"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": "27",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
"uri":"/?rxtest=wwwwwwwwwwwwwwwwwwwwwowwwwwwwwwww",
|
||||
"method":"HEAD",
|
||||
"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"
|
||||
},
|
||||
"body":[
|
||||
"no need."
|
||||
]
|
||||
},
|
||||
"expected":{
|
||||
"debug_log":"rx: regex error 'MATCH_LIMIT' for pattern",
|
||||
"error_log":"Matched \"Operator `StrEq' with parameter `1' against variable `TX:MSC_PCRE_LIMITS_EXCEEDED'"
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecPcreMatchLimit 2",
|
||||
"SecRule ARGS:rxtest \"@rx (w+)+$\" \"id:1,phase:1,pass,t:trim,block\"",
|
||||
"SecRule TX:MSC_PCRE_LIMITS_EXCEEDED \"@streq 1\" \"id:2,phase:1,pass,t:trim,block\""
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -162,6 +162,57 @@
|
|||
"SecRuleEngine On",
|
||||
"SecRule MULTIPART_PART_HEADERS:parm2 \"@rx content-type:.*jpeg\" \"phase:2,deny,status:403,id:500074,t:lowercase\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MULTIPART_PART_HEADERS (check EOL)",
|
||||
"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":"249",
|
||||
"Content-Type":"multipart/form-data; boundary=-----------------------------69343412719991675451336310646",
|
||||
"Expect":"100-continue"
|
||||
},
|
||||
"uri":"/",
|
||||
"method":"POST",
|
||||
"body":[
|
||||
"-------------------------------69343412719991675451336310646",
|
||||
"Content-Disposition: form-data; name=\"file\"; filename=\"New Text Document.txt\"",
|
||||
"Content-Type: text/plain; charset=utf-8\r\n",
|
||||
"",
|
||||
"1",
|
||||
"-------------------------------69343412719991675451336310646--"
|
||||
]
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"body":[
|
||||
"no need."
|
||||
]
|
||||
},
|
||||
"expected":{
|
||||
"http_code": 200
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule MULTIPART_PART_HEADERS \"@rx ^content-type\\s*+:\\s*+(.*)$\" \"id:922110,phase:2,deny,capture,t:none,t:lowercase,chain\"",
|
||||
"SecRule TX:1 \"!@rx ^text/plain; charset=(?:iso-8859-15?|windows-1252|utf-8)$\" \"t:lowercase\""
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue