mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 05:45:59 +03:00
Compare commits
107 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a07ed61e74 | ||
|
4e2788eb47 | ||
|
f9f4011a4b | ||
|
62cb73f31d | ||
|
8b3269f4d1 | ||
|
e879711d87 | ||
|
9fea1ca454 | ||
|
47bc24a808 | ||
|
12809656a6 | ||
|
ea51a663f1 | ||
|
d19d3b4785 | ||
|
67f32a4e63 | ||
|
6c6d94fc66 | ||
|
0f402f33fd | ||
|
01c427f6be | ||
|
31fb9390c2 | ||
|
2ee45de2fc | ||
|
0ac551b070 | ||
|
013c8c2c7b | ||
|
d8574c8c08 | ||
|
37948704df | ||
|
28bc3a98df | ||
|
72e3abdd12 | ||
|
f2170d8576 | ||
|
c60709a58c | ||
|
1ff9f2a943 | ||
|
690355b297 | ||
|
78b9cb7b57 | ||
|
5d05ba359c | ||
|
9fb75d2c9a | ||
|
abed778b4a | ||
|
8d15991fb4 | ||
|
b8a22bb67a | ||
|
7e3c807c0d | ||
|
bb70ff06a4 | ||
|
08b70e006b | ||
|
79d55037c0 | ||
|
9a8ce8b5f5 | ||
|
cf24aeaead | ||
|
6089b6b06b | ||
|
31507404e6 | ||
|
f64ea2a708 | ||
|
1362479d34 | ||
|
8d3b2cacc4 | ||
|
a17193f7af | ||
|
de624f9460 | ||
|
7660125da6 | ||
|
0caf30679f | ||
|
0bcabf3208 | ||
|
aab47091b1 | ||
|
990d99b1fb | ||
|
220caa5abc | ||
|
a3876e3c99 | ||
|
d228ea6607 | ||
|
89442ede16 | ||
|
e8dc60ee06 | ||
|
bf707de08f | ||
|
0b62b7eb85 | ||
|
91a45e79bd | ||
|
2135c8934e | ||
|
8947346cd4 | ||
|
67429307cc | ||
|
0c7ea21a26 | ||
|
72de7e8400 | ||
|
0bf60208af | ||
|
2000f4c048 | ||
|
159f6120aa | ||
|
bbe7eda693 | ||
|
0fcd257fc4 | ||
|
fedc70983c | ||
|
5b1c6fbf68 | ||
|
eedfed873e | ||
|
f0aa0700fe | ||
|
90be54e25e | ||
|
3dc9fe990c | ||
|
e3678764e5 | ||
|
22fee1296d | ||
|
b82d600049 | ||
|
797f7dc4b2 | ||
|
6408bf9237 | ||
|
37c0de363e | ||
|
029684c294 | ||
|
3e95614699 | ||
|
b42602f400 | ||
|
8ae8374be5 | ||
|
f62de58632 | ||
|
9e41a53760 | ||
|
01a0615887 | ||
|
80019da75e | ||
|
7a986c7bae | ||
|
8f00f4700f | ||
|
42280d213d | ||
|
c3c2c6f280 | ||
|
dbdd6318ff | ||
|
d3c1ad7177 | ||
|
dc40880663 | ||
|
1a2b13967f | ||
|
d68aef320c | ||
|
b97b61b711 | ||
|
6a2eee629c | ||
|
10d1c2be74 | ||
|
e92507868e | ||
|
784cf0b64c | ||
|
a07d0c7d34 | ||
|
106ed22b6d | ||
|
c6433df7b2 | ||
|
4fb22466a0 |
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -26,7 +26,7 @@ jobs:
|
||||
- {label: "wo geoip", opt: "--without-geoip" }
|
||||
- {label: "wo ssdeep", opt: "--without-ssdeep" }
|
||||
- {label: "with lmdb", opt: "--with-lmdb" }
|
||||
- {label: "with pcre2", opt: "--with-pcre2" }
|
||||
- {label: "with pcre", opt: "--with-pcre" }
|
||||
exclude:
|
||||
- platform: {label: "x32"}
|
||||
configure: {label: "wo geoip"}
|
||||
@ -88,7 +88,7 @@ jobs:
|
||||
- {label: "wo geoip", opt: "--without-geoip" }
|
||||
- {label: "wo ssdeep", opt: "--without-ssdeep" }
|
||||
- {label: "with lmdb", opt: "--with-lmdb" }
|
||||
- {label: "with pcre2", opt: "--with-pcre2" }
|
||||
- {label: "with pcre", opt: "--with-pcre" }
|
||||
steps:
|
||||
- name: Setup Dependencies
|
||||
# curl, pcre2 not installed because they're already
|
||||
|
@ -63,7 +63,7 @@ cppcheck:
|
||||
--enable=warning,style,performance,portability,unusedFunction,missingInclude \
|
||||
--inconclusive \
|
||||
--template="warning: {file},{line},{severity},{id},{message}" \
|
||||
-I headers -I . -I others -I src -I others/mbedtls/include \
|
||||
-I headers -I . -I $(top_srcdir)/others -I $(top_srcdir)/src -I $(top_srcdir)/others/mbedtls/include \
|
||||
--error-exitcode=1 \
|
||||
-i "src/parser/seclang-parser.cc" -i "src/parser/seclang-scanner.cc" \
|
||||
-i others \
|
||||
|
@ -219,8 +219,8 @@ the utilities, follow the commands listed below:
|
||||
$ cd /path/to/your/ModSecurity
|
||||
$ git submodule foreach git pull
|
||||
$ cd test
|
||||
$ ./regression-tests
|
||||
$ ./unit-tests
|
||||
$ ./regression_tests
|
||||
$ ./unit_tests
|
||||
```
|
||||
|
||||
### Debugging
|
||||
|
@ -21,8 +21,8 @@ AC_ARG_WITH(
|
||||
[test_paths="${with_pcre}"],
|
||||
[test_paths="/usr/local/libpcre /usr/local/pcre /usr/local /opt/libpcre /opt/pcre /opt /usr /opt/local"])
|
||||
|
||||
if test "x${with_pcre2}" != "x" && test "x${with_pcre2}" != "xno"; then
|
||||
AC_MSG_NOTICE([pcre2 specified; omitting check for pcre])
|
||||
if test "x${with_pcre}" == "x" && test "x${with_pcre}" != "xno"; then
|
||||
AC_MSG_NOTICE([Support for pcre not requested; omitting check for pcre])
|
||||
else
|
||||
|
||||
AC_MSG_CHECKING([for libpcre config script])
|
||||
@ -106,6 +106,7 @@ else
|
||||
LIBS=$save_LIBS
|
||||
fi
|
||||
|
||||
PCRE_CFLAGS="-DWITH_PCRE ${PCRE_CFLAGS}"
|
||||
AC_SUBST(PCRE_CONFIG)
|
||||
AC_SUBST(PCRE_VERSION)
|
||||
AC_SUBST(PCRE_CPPFLAGS)
|
||||
|
@ -29,10 +29,12 @@ if test "x${with_pcre2}" == "xno"; then
|
||||
AC_MSG_NOTICE([Support for PCRE2 was disabled by the utilization of --without-pcre2 or --with-pcre2=no])
|
||||
PCRE2_DISABLED=yes
|
||||
else
|
||||
if test "x${with_pcre2}" == "xyes"; then
|
||||
PCRE2_MANDATORY=yes
|
||||
AC_MSG_NOTICE([PCRE2 support was marked as mandatory by the utilization of --with-pcre2=yes])
|
||||
fi
|
||||
PCRE2_MANDATORY=yes
|
||||
AC_MSG_NOTICE([PCRE2 is enabled by default.])
|
||||
# if test "x${with_pcre2}" == "xyes"; then
|
||||
# PCRE2_MANDATORY=yes
|
||||
# AC_MSG_NOTICE([PCRE2 support was marked as mandatory by the utilization of --with-pcre2=yes])
|
||||
# fi
|
||||
# for x in ${PCRE2_POSSIBLE_LIB_NAMES}; do
|
||||
# CHECK_FOR_PCRE2_AT(${x})
|
||||
# if test -n "${PCRE2_VERSION}"; then
|
||||
@ -96,9 +98,14 @@ else
|
||||
AC_MSG_NOTICE([PCRE2 is disabled by default.])
|
||||
else
|
||||
PCRE2_FOUND=1
|
||||
AC_MSG_NOTICE([using PCRE2 v${PCRE2_VERSION}])
|
||||
PCRE2_CFLAGS="-DWITH_PCRE2 ${PCRE2_CFLAGS}"
|
||||
PCRE2_CFLAGS="${PCRE2_CFLAGS}"
|
||||
PCRE2_DISPLAY="${PCRE2_LDADD}, ${PCRE2_CFLAGS}"
|
||||
AC_MSG_NOTICE([using PCRE2_VERSION ${PCRE2_VERSION}])
|
||||
AC_MSG_NOTICE([using PCRE2_LDADD ${PCRE2_LDADD}])
|
||||
AC_MSG_NOTICE([using PCRE2_LIBS ${PCRE2_LIBS}])
|
||||
AC_MSG_NOTICE([using PCRE2_LDFLAGS ${PCRE2_LDFLAGS}])
|
||||
AC_MSG_NOTICE([using PCRE2_CFLAGS ${PCRE2_CFLAGS}])
|
||||
AC_MSG_NOTICE([using PCRE2_DISPLAY ${PCRE2_DISPLAY}])
|
||||
AC_SUBST(PCRE2_VERSION)
|
||||
AC_SUBST(PCRE2_LDADD)
|
||||
AC_SUBST(PCRE2_LIBS)
|
||||
|
36
configure.ac
36
configure.ac
@ -42,7 +42,7 @@ AC_PREFIX_DEFAULT([/usr/local/modsecurity])
|
||||
|
||||
|
||||
# General automake options.
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
|
||||
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
|
||||
|
||||
|
||||
# Check for dependencies (C++, AR, Lex, Yacc and Make)
|
||||
@ -109,24 +109,19 @@ AM_CONDITIONAL([YAJL_VERSION], [test "$YAJL_VERSION" != ""])
|
||||
|
||||
# Check for LibGeoIP
|
||||
PROG_GEOIP
|
||||
AM_CONDITIONAL([GEOIP_CFLAGS], [test "GEOIP_CFLAGS" != ""])
|
||||
|
||||
# Check for MaxMind
|
||||
PROG_MAXMIND
|
||||
AM_CONDITIONAL([MAXMIND_CFLAGS], [test "MAXMIND_CFLAGS" != ""])
|
||||
|
||||
|
||||
# Check for LMDB
|
||||
PROG_LMDB
|
||||
AM_CONDITIONAL([LMDB_CFLAGS], [test "LMDB_CFLAGS" != ""])
|
||||
|
||||
# Check for SSDEEP
|
||||
CHECK_SSDEEP
|
||||
AM_CONDITIONAL([SSDEEP_CFLAGS], [test "SSDEEP_CFLAGS" != ""])
|
||||
|
||||
# Check for LUA
|
||||
CHECK_LUA
|
||||
AM_CONDITIONAL([LUA_CFLAGS], [test "LUA_CFLAGS" != ""])
|
||||
|
||||
|
||||
#
|
||||
@ -146,16 +141,16 @@ CHECK_LIBXML2
|
||||
|
||||
|
||||
#
|
||||
# Check for libpcre
|
||||
# Check for libpcre only if explicitly requested
|
||||
#
|
||||
CHECK_PCRE
|
||||
|
||||
|
||||
#
|
||||
# Check for pcre2
|
||||
#
|
||||
PROG_PCRE2
|
||||
AM_CONDITIONAL([PCRE2_CFLAGS], [test "PCRE2_CFLAGS" != ""])
|
||||
if test "x${with_pcre}" != "x" && test "x${with_pcre}" != "xno"; then
|
||||
CHECK_PCRE
|
||||
else
|
||||
#
|
||||
# Check for pcre2
|
||||
#
|
||||
PROG_PCRE2
|
||||
fi
|
||||
|
||||
|
||||
# Checks for header files.
|
||||
@ -587,6 +582,17 @@ if test "x$LUA_FOUND" = "x2"; then
|
||||
echo " + LUA ....disabled"
|
||||
fi
|
||||
|
||||
##PCRE
|
||||
if test "x${with_pcre}" != "x" \
|
||||
&& test "x${with_pcre}" != "xno" \
|
||||
&& test "x${PCRE_VERSION}" == "x"; then
|
||||
AC_MSG_NOTICE([*** pcre library not found.])
|
||||
else
|
||||
echo " + PCRE ....found "
|
||||
echo " using pcre v${PCRE_VERSION}"
|
||||
echo " ${PCRE_LDADD}, ${PCRE_CFLAGS}"
|
||||
fi
|
||||
|
||||
|
||||
## PCRE2
|
||||
if test "x$PCRE2_FOUND" = "x0"; then
|
||||
|
@ -38,7 +38,7 @@ RulesSet *rules = NULL;
|
||||
ModSecurity *modsec = NULL;
|
||||
|
||||
|
||||
void process_special_request (int j) {
|
||||
static void process_special_request (int j) {
|
||||
Transaction *transaction;
|
||||
transaction = msc_new_transaction(modsec, rules, NULL);
|
||||
|
||||
@ -60,7 +60,7 @@ void process_special_request (int j) {
|
||||
msc_transaction_cleanup(transaction);
|
||||
}
|
||||
|
||||
void process_request (int j) {
|
||||
static void process_request (int j) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < REQUESTS_PER_PROCESS; i++) {
|
||||
|
@ -14,6 +14,7 @@ multithread_LDADD = \
|
||||
$(MAXMIND_LDADD) \
|
||||
$(LUA_LDADD) \
|
||||
$(PCRE_LDADD) \
|
||||
$(PCRE2_LDADD) \
|
||||
$(SSDEEP_LDADD) \
|
||||
$(YAJL_LDADD)
|
||||
|
||||
@ -46,6 +47,7 @@ multithread_CPPFLAGS = \
|
||||
$(LMDB_CFLAGS) \
|
||||
$(LUA_CFLAGS) \
|
||||
$(PCRE_CFLAGS) \
|
||||
$(PCRE2_CFLAGS) \
|
||||
$(LIBXML2_CFLAGS)
|
||||
|
||||
|
||||
|
@ -14,6 +14,7 @@ simple_request_LDADD = \
|
||||
$(MAXMIND_LDADD) \
|
||||
$(LUA_LDADD) \
|
||||
$(PCRE_LDADD) \
|
||||
$(PCRE2_LDADD) \
|
||||
$(SSDEEP_LDADD) \
|
||||
$(YAJL_LDADD)
|
||||
|
||||
@ -46,6 +47,7 @@ simple_request_CPPFLAGS = \
|
||||
$(LMDB_CFLAGS) \
|
||||
$(LUA_CFLAGS) \
|
||||
$(PCRE_CFLAGS) \
|
||||
$(PCRE2_CFLAGS) \
|
||||
$(LIBXML2_CFLAGS)
|
||||
|
||||
|
||||
|
@ -14,6 +14,7 @@ read_LDADD = \
|
||||
$(LMDB_LDADD) \
|
||||
$(LUA_LDADD) \
|
||||
$(PCRE_LDADD) \
|
||||
$(PCRE2_LDADD) \
|
||||
$(SSDEEP_LDADD) \
|
||||
$(YAJL_LDADD)
|
||||
|
||||
@ -46,6 +47,7 @@ read_CPPFLAGS = \
|
||||
$(LMDB_CFLAGS) \
|
||||
$(LUA_CFLAGS) \
|
||||
$(PCRE_CFLAGS) \
|
||||
$(PCRE2_CFLAGS) \
|
||||
$(LIBXML2_CFLAGS)
|
||||
|
||||
|
||||
|
@ -14,6 +14,7 @@ simple_request_LDADD = \
|
||||
$(LMDB_LDADD) \
|
||||
$(LUA_LDADD) \
|
||||
$(PCRE_LDADD) \
|
||||
$(PCRE2_LDADD) \
|
||||
$(SSDEEP_LDADD) \
|
||||
$(YAJL_LDADD)
|
||||
|
||||
@ -46,6 +47,7 @@ simple_request_CPPFLAGS = \
|
||||
$(LMDB_CFLAGS) \
|
||||
$(LUA_CFLAGS) \
|
||||
$(PCRE_CFLAGS) \
|
||||
$(PCRE2_CFLAGS) \
|
||||
$(LIBXML2_CFLAGS)
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
|
@ -153,17 +153,18 @@ class AuditLog {
|
||||
bool setStorageDirMode(int permission);
|
||||
bool setFileMode(int permission);
|
||||
bool setStatus(AuditLogStatus new_status);
|
||||
bool setRelevantStatus(const std::basic_string<char>& new_relevant_status);
|
||||
bool setFilePath1(const std::basic_string<char>& path);
|
||||
bool setFilePath2(const std::basic_string<char>& path);
|
||||
bool setStorageDir(const std::basic_string<char>& path);
|
||||
bool setRelevantStatus(std::string_view new_relevant_status);
|
||||
bool setFilePath1(std::string_view path);
|
||||
bool setFilePath2(std::string_view path);
|
||||
bool setStorageDir(std::string_view path);
|
||||
bool setPrefix(std::string_view prefix);
|
||||
bool setFormat(AuditLogFormat fmt);
|
||||
|
||||
int getDirectoryPermission() const;
|
||||
int getFilePermission() const;
|
||||
int getParts() const;
|
||||
|
||||
bool setParts(const std::basic_string<char>& new_parts);
|
||||
bool setParts(std::string_view new_parts);
|
||||
bool setType(AuditLogType audit_type);
|
||||
|
||||
bool init(std::string *error);
|
||||
@ -173,8 +174,8 @@ class AuditLog {
|
||||
bool saveIfRelevant(Transaction *transaction, int parts);
|
||||
bool isRelevant(int status);
|
||||
|
||||
static int addParts(int parts, const std::string& new_parts);
|
||||
static int removeParts(int parts, const std::string& new_parts);
|
||||
static int addParts(int parts, std::string_view new_parts);
|
||||
static int removeParts(int parts, std::string_view new_parts);
|
||||
|
||||
void setCtlAuditEngineActive() {
|
||||
m_ctlAuditEngineActive = true;
|
||||
@ -182,31 +183,32 @@ class AuditLog {
|
||||
|
||||
bool merge(AuditLog *from, std::string *error);
|
||||
|
||||
std::string m_path1;
|
||||
std::string m_path2;
|
||||
std::string m_storage_dir;
|
||||
std::string m_path1 = std::string("");
|
||||
std::string m_path2 = std::string("");
|
||||
std::string m_storage_dir = std::string("");
|
||||
std::string m_prefix = std::string("");
|
||||
|
||||
AuditLogFormat m_format;
|
||||
AuditLogFormat m_format = NotSetAuditLogFormat;
|
||||
|
||||
protected:
|
||||
int m_parts;
|
||||
int m_parts = -1;
|
||||
int m_defaultParts = AAuditLogPart | BAuditLogPart | CAuditLogPart
|
||||
| FAuditLogPart | HAuditLogPart | ZAuditLogPart;
|
||||
|
||||
int m_filePermission;
|
||||
int m_filePermission = -1;
|
||||
int m_defaultFilePermission = 0640;
|
||||
|
||||
int m_directoryPermission;
|
||||
int m_directoryPermission = -1;
|
||||
int m_defaultDirectoryPermission = 0750;
|
||||
|
||||
private:
|
||||
AuditLogStatus m_status;
|
||||
AuditLogStatus m_status = NotSetLogStatus;
|
||||
|
||||
AuditLogType m_type;
|
||||
std::string m_relevant;
|
||||
AuditLogType m_type = NotSetAuditLogType;
|
||||
std::string m_relevant = std::string("");
|
||||
|
||||
audit_log::writer::Writer *m_writer;
|
||||
bool m_ctlAuditEngineActive; // rules have at least one action On or RelevantOnly
|
||||
audit_log::writer::Writer *m_writer = nullptr;
|
||||
bool m_ctlAuditEngineActive = false; // rules have at least one action On or RelevantOnly
|
||||
};
|
||||
|
||||
|
||||
|
@ -59,7 +59,6 @@ class RuleWithOperator : public RuleWithActions {
|
||||
|
||||
static void updateMatchedVars(Transaction *trasn, const std::string &key,
|
||||
const std::string &value);
|
||||
static void cleanMatchedVars(Transaction *trasn);
|
||||
|
||||
|
||||
const std::string& getOperatorName() const;
|
||||
|
@ -53,8 +53,8 @@ class RulesExceptions {
|
||||
bool contains(int a);
|
||||
bool merge(RulesExceptions *from);
|
||||
|
||||
bool loadRemoveRuleByMsg(const std::string &msg, std::string *error);
|
||||
bool loadRemoveRuleByTag(const std::string &msg, std::string *error);
|
||||
bool loadRemoveRuleByMsg(const std::string &msg, const std::string *error);
|
||||
bool loadRemoveRuleByTag(const std::string &msg, const std::string *error);
|
||||
|
||||
bool loadUpdateTargetByMsg(const std::string &msg,
|
||||
std::unique_ptr<std::vector<std::unique_ptr<variables::Variable> > > v,
|
||||
|
@ -80,6 +80,8 @@ class RulesSet : public RulesSetProperties {
|
||||
void debug(int level, const std::string &id, const std::string &uri,
|
||||
const std::string &msg);
|
||||
|
||||
static void cleanMatchedVars(Transaction *trans);
|
||||
|
||||
RulesSetPhases m_rulesSetPhases;
|
||||
private:
|
||||
#ifndef NO_LOGS
|
||||
|
@ -13,6 +13,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <ctime>
|
||||
@ -22,6 +30,8 @@
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <cstdint>
|
||||
#endif
|
||||
|
||||
|
||||
@ -52,6 +62,11 @@
|
||||
to = (from == PropertyNotSetBodyLimitAction) ? default : from; \
|
||||
}
|
||||
|
||||
#define merge_xmlargparse_value(to, from, default) \
|
||||
if (to == PropertyNotSetConfigXMLParseXmlIntoArgs) { \
|
||||
to = (from == PropertyNotSetConfigXMLParseXmlIntoArgs) ? default : from; \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace modsecurity {
|
||||
@ -63,46 +78,132 @@ class Driver;
|
||||
using modsecurity::debug_log::DebugLog;
|
||||
using modsecurity::audit_log::AuditLog;
|
||||
|
||||
/** @ingroup ModSecurity_CPP_API */
|
||||
class ConfigInt {
|
||||
public:
|
||||
ConfigInt() : m_set(false), m_value(0) { }
|
||||
bool m_set;
|
||||
int m_value;
|
||||
// template for different numeric int types
|
||||
template <typename T>
|
||||
class ConfigValue {
|
||||
public:
|
||||
bool m_set = false;
|
||||
T m_value = 0;
|
||||
|
||||
void merge(const ConfigInt *from) {
|
||||
if (m_set == true || from->m_set == false) {
|
||||
ConfigValue() = default;
|
||||
|
||||
void merge(const ConfigValue<T>* from) {
|
||||
if (m_set || !from->m_set) {
|
||||
return;
|
||||
}
|
||||
m_set = true;
|
||||
m_value = from->m_value;
|
||||
return;
|
||||
}
|
||||
|
||||
// default parser
|
||||
bool parse(const std::string& a, std::string* errmsg = nullptr) {
|
||||
|
||||
// use an alias type because the template can convert both signed and unsigned int
|
||||
using LimitSigned = std::conditional_t<std::is_signed_v<T>, std::int64_t, std::uint64_t>;
|
||||
LimitSigned val;
|
||||
|
||||
// clear errno variable, wee need that later
|
||||
errno = 0;
|
||||
|
||||
try {
|
||||
if constexpr (std::is_signed_v<T>) {
|
||||
val = static_cast<std::int64_t>(std::stoll(a));
|
||||
} else {
|
||||
val = static_cast<std::uint64_t>(std::stoull(a));
|
||||
}
|
||||
}
|
||||
catch (const std::invalid_argument&) {
|
||||
// probably can't occur, but we handle it anyway
|
||||
set_error(errmsg, "Invalid number format (not numeric)");
|
||||
return false;
|
||||
}
|
||||
catch (const std::out_of_range&) {
|
||||
// the value is out of range, we can not handle it
|
||||
set_error(errmsg, "Number out of range");
|
||||
return false;
|
||||
}
|
||||
catch (...) { // NOSONAR
|
||||
// we don't need to handle all exceptions, the engine's BISON parser
|
||||
// does not allow other symbols than numbers
|
||||
set_error(errmsg, "An unknown error occurred while parsing number.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
// The first condition will be true when the value is bigger than int64/uint64 maximum value.
|
||||
// The second condition checks whether the value fits into int64/uint64, but not
|
||||
// into the designed type, e.g., uint32; in that case the errno will be 0, but
|
||||
// we must check the value is not bigger than the defined maximum of the class.
|
||||
(errno == ERANGE && val == std::numeric_limits<LimitSigned>::max())
|
||||
||
|
||||
(val > static_cast<LimitSigned>(maxValue()))
|
||||
) {
|
||||
set_error(errmsg, "Value is too big.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
// same as above
|
||||
(errno == ERANGE && val == std::numeric_limits<LimitSigned>::min())
|
||||
||
|
||||
(val < static_cast<LimitSigned>(minValue()))
|
||||
) {
|
||||
set_error(errmsg, "Value is too small.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_value = static_cast<T>(val);
|
||||
m_set = true;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
// derived classes must implement the maxValue
|
||||
virtual T maxValue() const = 0;
|
||||
// minValue is optional
|
||||
virtual T minValue() const { return 0; }
|
||||
|
||||
private:
|
||||
static inline void set_error(std::string* err, const char* msg) {
|
||||
if (err) {
|
||||
*err = msg;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** @ingroup ModSecurity_CPP_API */
|
||||
|
||||
class ConfigDouble {
|
||||
public:
|
||||
ConfigDouble() : m_set(false), m_value(0) { }
|
||||
bool m_set;
|
||||
double m_value;
|
||||
class ConfigInt : public ConfigValue<int32_t> {
|
||||
protected:
|
||||
int32_t minValue() const override {
|
||||
return std::numeric_limits<int32_t>::min();
|
||||
}
|
||||
int32_t maxValue() const override {
|
||||
return std::numeric_limits<int32_t>::max();
|
||||
}
|
||||
};
|
||||
|
||||
void merge(const ConfigDouble *from) {
|
||||
if (m_set == true || from->m_set == false) {
|
||||
return;
|
||||
}
|
||||
m_set = true;
|
||||
m_value = from->m_value;
|
||||
return;
|
||||
class ConfigUnsignedInt : public ConfigValue<uint32_t> {
|
||||
protected:
|
||||
uint32_t maxValue() const override {
|
||||
return std::numeric_limits<uint32_t>::max();
|
||||
}
|
||||
};
|
||||
|
||||
class ConfigUnsignedLong : public ConfigValue<uint64_t> {
|
||||
protected:
|
||||
uint64_t maxValue() const override {
|
||||
return std::numeric_limits<uint64_t>::max();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ConfigString {
|
||||
public:
|
||||
ConfigString() : m_set(false), m_value("") { }
|
||||
bool m_set;
|
||||
std::string m_value;
|
||||
bool m_set = false;
|
||||
std::string m_value = "";
|
||||
ConfigString() = default;
|
||||
|
||||
void merge(const ConfigString *from) {
|
||||
if (m_set == true || from->m_set == false) {
|
||||
@ -117,10 +218,10 @@ class ConfigString {
|
||||
|
||||
class ConfigSet {
|
||||
public:
|
||||
ConfigSet() : m_set(false), m_clear(false) { }
|
||||
bool m_set;
|
||||
bool m_clear;
|
||||
bool m_set = false;
|
||||
bool m_clear = false;
|
||||
std::set<std::string> m_value;
|
||||
ConfigSet() = default;
|
||||
};
|
||||
|
||||
|
||||
@ -177,6 +278,7 @@ class RulesSetProperties {
|
||||
m_secRequestBodyAccess(PropertyNotSetConfigBoolean),
|
||||
m_secResponseBodyAccess(PropertyNotSetConfigBoolean),
|
||||
m_secXMLExternalEntity(PropertyNotSetConfigBoolean),
|
||||
m_secXMLParseXmlIntoArgs(PropertyNotSetConfigXMLParseXmlIntoArgs),
|
||||
m_tmpSaveUploadedFiles(PropertyNotSetConfigBoolean),
|
||||
m_uploadKeepFiles(PropertyNotSetConfigBoolean),
|
||||
m_debugLog(new DebugLog()),
|
||||
@ -191,6 +293,7 @@ class RulesSetProperties {
|
||||
m_secRequestBodyAccess(PropertyNotSetConfigBoolean),
|
||||
m_secResponseBodyAccess(PropertyNotSetConfigBoolean),
|
||||
m_secXMLExternalEntity(PropertyNotSetConfigBoolean),
|
||||
m_secXMLParseXmlIntoArgs(PropertyNotSetConfigXMLParseXmlIntoArgs),
|
||||
m_tmpSaveUploadedFiles(PropertyNotSetConfigBoolean),
|
||||
m_uploadKeepFiles(PropertyNotSetConfigBoolean),
|
||||
m_debugLog(debugLog),
|
||||
@ -218,7 +321,8 @@ class RulesSetProperties {
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* The ConfigBoolean enumerator defines the states for configuration boolean values.
|
||||
* The default value is PropertyNotSetConfigBoolean.
|
||||
*/
|
||||
enum ConfigBoolean {
|
||||
TrueConfigBoolean,
|
||||
@ -226,6 +330,18 @@ class RulesSetProperties {
|
||||
PropertyNotSetConfigBoolean
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* The ConfigXMLParseXmlIntoArgs enumerator defines the states for the configuration
|
||||
* XMLParseXmlIntoArgs values.
|
||||
* The default value is PropertyNotSetConfigXMLParseXmlIntoArgs.
|
||||
*/
|
||||
enum ConfigXMLParseXmlIntoArgs {
|
||||
TrueConfigXMLParseXmlIntoArgs,
|
||||
FalseConfigXMLParseXmlIntoArgs,
|
||||
OnlyArgsConfigXMLParseXmlIntoArgs,
|
||||
PropertyNotSetConfigXMLParseXmlIntoArgs
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
@ -311,7 +427,7 @@ class RulesSetProperties {
|
||||
};
|
||||
|
||||
|
||||
static const char *ruleEngineStateString(RuleEngine i) {
|
||||
static std::string ruleEngineStateString(RuleEngine i) {
|
||||
switch (i) {
|
||||
case DisabledRuleEngine:
|
||||
return "Disabled";
|
||||
@ -322,7 +438,7 @@ class RulesSetProperties {
|
||||
case PropertyNotSetRuleEngine:
|
||||
return "PropertyNotSet/DetectionOnly";
|
||||
}
|
||||
return NULL;
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
|
||||
@ -338,6 +454,19 @@ class RulesSetProperties {
|
||||
}
|
||||
}
|
||||
|
||||
static std::string configXMLParseXmlIntoArgsString(ConfigXMLParseXmlIntoArgs i) {
|
||||
switch (i) {
|
||||
case TrueConfigXMLParseXmlIntoArgs:
|
||||
return "True";
|
||||
case FalseConfigXMLParseXmlIntoArgs:
|
||||
return "False";
|
||||
case OnlyArgsConfigXMLParseXmlIntoArgs:
|
||||
return "OnlyArgs";
|
||||
case PropertyNotSetConfigXMLParseXmlIntoArgs:
|
||||
default:
|
||||
return "Not set";
|
||||
}
|
||||
}
|
||||
|
||||
static int mergeProperties(RulesSetProperties *from,
|
||||
RulesSetProperties *to, std::ostringstream *err) {
|
||||
@ -357,6 +486,10 @@ class RulesSetProperties {
|
||||
from->m_secXMLExternalEntity,
|
||||
PropertyNotSetConfigBoolean);
|
||||
|
||||
merge_xmlargparse_value(to->m_secXMLParseXmlIntoArgs,
|
||||
from->m_secXMLParseXmlIntoArgs,
|
||||
PropertyNotSetConfigXMLParseXmlIntoArgs);
|
||||
|
||||
merge_boolean_value(to->m_uploadKeepFiles,
|
||||
from->m_uploadKeepFiles,
|
||||
PropertyNotSetConfigBoolean);
|
||||
@ -464,16 +597,17 @@ class RulesSetProperties {
|
||||
ConfigBoolean m_secRequestBodyAccess;
|
||||
ConfigBoolean m_secResponseBodyAccess;
|
||||
ConfigBoolean m_secXMLExternalEntity;
|
||||
ConfigXMLParseXmlIntoArgs m_secXMLParseXmlIntoArgs;
|
||||
ConfigBoolean m_tmpSaveUploadedFiles;
|
||||
ConfigBoolean m_uploadKeepFiles;
|
||||
ConfigDouble m_argumentsLimit;
|
||||
ConfigDouble m_requestBodyJsonDepthLimit;
|
||||
ConfigDouble m_requestBodyLimit;
|
||||
ConfigDouble m_requestBodyNoFilesLimit;
|
||||
ConfigDouble m_responseBodyLimit;
|
||||
ConfigInt m_pcreMatchLimit;
|
||||
ConfigInt m_uploadFileLimit;
|
||||
ConfigInt m_uploadFileMode;
|
||||
ConfigUnsignedInt m_argumentsLimit;
|
||||
ConfigUnsignedInt m_requestBodyJsonDepthLimit;
|
||||
ConfigUnsignedLong m_requestBodyLimit;
|
||||
ConfigUnsignedLong m_requestBodyNoFilesLimit;
|
||||
ConfigUnsignedLong m_responseBodyLimit;
|
||||
ConfigUnsignedInt m_pcreMatchLimit;
|
||||
ConfigUnsignedInt m_uploadFileLimit;
|
||||
ConfigUnsignedInt m_uploadFileMode;
|
||||
DebugLog *m_debugLog;
|
||||
OnFailedRemoteRulesAction m_remoteRulesActionOnFailed;
|
||||
RuleEngine m_secRuleEngine;
|
||||
|
@ -80,15 +80,14 @@ typedef struct Rules_t RulesSet;
|
||||
|
||||
#define LOGFY_ADD(a, b) \
|
||||
yajl_gen_string(g, reinterpret_cast<const unsigned char*>(a), strlen(a)); \
|
||||
if (b == NULL) { \
|
||||
if (b.data() == NULL) { \
|
||||
yajl_gen_string(g, reinterpret_cast<const unsigned char*>(""), \
|
||||
strlen("")); \
|
||||
} else { \
|
||||
yajl_gen_string(g, reinterpret_cast<const unsigned char*>(b), \
|
||||
strlen(b)); \
|
||||
yajl_gen_string(g, reinterpret_cast<const unsigned char*>(b.data()), \
|
||||
b.length()); \
|
||||
}
|
||||
|
||||
|
||||
#define LOGFY_ADD_INT(a, b) \
|
||||
yajl_gen_string(g, reinterpret_cast<const unsigned char*>(a), strlen(a)); \
|
||||
yajl_gen_number(g, reinterpret_cast<const char*>(b), strlen(b));
|
||||
@ -412,7 +411,7 @@ class Transaction : public TransactionAnchoredVariables, public TransactionSecMa
|
||||
int getRuleEngineState() const;
|
||||
|
||||
std::string toJSON(int parts);
|
||||
std::string toOldAuditLogFormat(int parts, const std::string &trailer);
|
||||
std::string toOldAuditLogFormat(int parts, const std::string &trailer, const std::string &header);
|
||||
std::string toOldAuditLogFormatIndex(const std::string &filename,
|
||||
double size, const std::string &md5);
|
||||
|
||||
@ -619,6 +618,7 @@ class Transaction : public TransactionAnchoredVariables, public TransactionSecMa
|
||||
RequestBodyProcessor::JSON *m_json;
|
||||
|
||||
int m_secRuleEngine;
|
||||
int m_secXMLParseXmlIntoArgs;
|
||||
|
||||
std::string m_variableDuration;
|
||||
std::map<std::string, std::string> m_variableEnvs;
|
||||
|
@ -28,6 +28,6 @@ libmbedtls_la_SOURCES = \
|
||||
mbedtls/library/sha1.c \
|
||||
mbedtls/library/platform_util.c
|
||||
|
||||
libmbedtls_la_CFLAGS = -DMBEDTLS_CONFIG_FILE=\"mbedtls/mbedtls_config.h\" -Imbedtls/include
|
||||
libmbedtls_la_CFLAGS = -DMBEDTLS_CONFIG_FILE=\"mbedtls/mbedtls_config.h\" -I$(top_srcdir)/others/mbedtls/include
|
||||
libmbedtls_la_CPPFLAGS =
|
||||
libmbedtls_la_LIBADD =
|
||||
|
@ -68,21 +68,21 @@ libmodsecurity_includesub_actions_HEADERS = \
|
||||
|
||||
|
||||
noinst_HEADERS = \
|
||||
actions/*.h \
|
||||
actions/ctl/*.h \
|
||||
actions/data/*.h \
|
||||
actions/disruptive/*.h \
|
||||
actions/transformations/*.h \
|
||||
debug_log/*.h \
|
||||
audit_log/writer/*.h \
|
||||
collection/backend/*.h \
|
||||
operators/*.h \
|
||||
parser/*.h \
|
||||
request_body_processor/*.h \
|
||||
utils/*.h \
|
||||
variables/*.h \
|
||||
engine/*.h \
|
||||
*.h
|
||||
$(wildcard actions/*.h) \
|
||||
$(wildcard actions/ctl/*.h) \
|
||||
$(wildcard actions/data/*.h) \
|
||||
$(wildcard actions/disruptive/*.h) \
|
||||
$(wildcard actions/transformations/*.h) \
|
||||
$(wildcard debug_log/*.h) \
|
||||
$(wildcard audit_log/writer/*.h) \
|
||||
$(wildcard collection/backend/*.h) \
|
||||
$(wildcard operators/*.h) \
|
||||
$(wildcard parser/*.h) \
|
||||
$(wildcard request_body_processor/*.h) \
|
||||
$(wildcard utils/*.h) \
|
||||
$(wildcard variables/*.h) \
|
||||
$(wildcard engine/*.h) \
|
||||
$(wildcard *.h)
|
||||
|
||||
|
||||
ENGINES = \
|
||||
@ -119,6 +119,7 @@ ACTIONS = \
|
||||
actions/chain.cc \
|
||||
actions/ctl/audit_log_parts.cc \
|
||||
actions/ctl/audit_engine.cc \
|
||||
actions/ctl/parse_xml_into_args.cc \
|
||||
actions/ctl/rule_engine.cc \
|
||||
actions/ctl/request_body_processor_json.cc \
|
||||
actions/ctl/request_body_processor_xml.cc \
|
||||
@ -307,13 +308,14 @@ libmodsecurity_la_CFLAGS =
|
||||
|
||||
|
||||
libmodsecurity_la_CPPFLAGS = \
|
||||
-I.. \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_builddir) \
|
||||
-g \
|
||||
-I../others \
|
||||
-I../others/mbedtls/include \
|
||||
-I$(top_srcdir)/others \
|
||||
-I$(top_srcdir)/others/mbedtls/include \
|
||||
-fPIC \
|
||||
-O3 \
|
||||
-I../headers \
|
||||
-I$(top_srcdir)/headers \
|
||||
$(CURL_CFLAGS) \
|
||||
$(GEOIP_CFLAGS) \
|
||||
$(GLOBAL_CPPFLAGS) \
|
||||
|
63
src/actions/ctl/parse_xml_into_args.cc
Normal file
63
src/actions/ctl/parse_xml_into_args.cc
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2025 OWASP ModSecurity project
|
||||
*
|
||||
* 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 OWASP.
|
||||
* directly using the email address modsecurity@owasp.org.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "src/actions/ctl/parse_xml_into_args.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "modsecurity/rules_set_properties.h"
|
||||
#include "modsecurity/rules_set.h"
|
||||
#include "modsecurity/transaction.h"
|
||||
|
||||
namespace modsecurity {
|
||||
namespace actions {
|
||||
namespace ctl {
|
||||
|
||||
|
||||
bool ParseXmlIntoArgs::init(std::string *error) {
|
||||
std::string what(m_parser_payload, 17, m_parser_payload.size() - 17);
|
||||
|
||||
if (what == "on") {
|
||||
m_secXMLParseXmlIntoArgs = RulesSetProperties::TrueConfigXMLParseXmlIntoArgs;
|
||||
} else if (what == "off") {
|
||||
m_secXMLParseXmlIntoArgs = RulesSetProperties::FalseConfigXMLParseXmlIntoArgs;
|
||||
} else if (what == "onlyargs") {
|
||||
m_secXMLParseXmlIntoArgs = RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs;
|
||||
} else {
|
||||
error->assign("Internal error. Expected: On, Off or OnlyArgs; " \
|
||||
"got: " + m_parser_payload);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseXmlIntoArgs::evaluate(RuleWithActions *rule, Transaction *transaction) {
|
||||
std::stringstream a;
|
||||
a << "Setting SecParseXmlIntoArgs to ";
|
||||
a << modsecurity::RulesSetProperties::configXMLParseXmlIntoArgsString(m_secXMLParseXmlIntoArgs);
|
||||
a << " as requested by a ctl:parseXmlIntoArgs action";
|
||||
|
||||
ms_dbg_a(transaction, 8, a.str());
|
||||
|
||||
transaction->m_secXMLParseXmlIntoArgs = m_secXMLParseXmlIntoArgs;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ctl
|
||||
} // namespace actions
|
||||
} // namespace modsecurity
|
48
src/actions/ctl/parse_xml_into_args.h
Normal file
48
src/actions/ctl/parse_xml_into_args.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* ModSecurity, http://www.modsecurity.org/
|
||||
* Copyright (c) 2025 OWASP ModSecurity Project
|
||||
*
|
||||
* 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 OWASP.
|
||||
* directly using the email address modsecurity@owasp.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "modsecurity/rules_set_properties.h"
|
||||
#include "modsecurity/actions/action.h"
|
||||
#include "modsecurity/transaction.h"
|
||||
|
||||
|
||||
#ifndef SRC_ACTIONS_CTL_PARSE_XML_INTO_ARGS_H_
|
||||
#define SRC_ACTIONS_CTL_PARSE_XML_INTO_ARGS_H_
|
||||
|
||||
namespace modsecurity {
|
||||
namespace actions {
|
||||
namespace ctl {
|
||||
|
||||
|
||||
class ParseXmlIntoArgs : public Action {
|
||||
public:
|
||||
explicit ParseXmlIntoArgs(const std::string &action)
|
||||
: Action(action),
|
||||
m_secXMLParseXmlIntoArgs(RulesSetProperties::PropertyNotSetConfigXMLParseXmlIntoArgs) { }
|
||||
|
||||
bool init(std::string *error) override;
|
||||
bool evaluate(RuleWithActions *rule, Transaction *transaction) override;
|
||||
|
||||
RulesSetProperties::ConfigXMLParseXmlIntoArgs m_secXMLParseXmlIntoArgs;
|
||||
};
|
||||
|
||||
|
||||
} // namespace ctl
|
||||
} // namespace actions
|
||||
} // namespace modsecurity
|
||||
|
||||
#endif // SRC_ACTIONS_CTL_PARSE_XML_INTO_ARGS_H_
|
@ -46,7 +46,7 @@ static inline bool encode(std::string &value) {
|
||||
int unicode_len = 0;
|
||||
unsigned int d = 0;
|
||||
unsigned char c;
|
||||
auto utf = &input[i];
|
||||
const auto* utf = &input[i];
|
||||
|
||||
c = *utf;
|
||||
|
||||
|
@ -51,25 +51,13 @@ namespace modsecurity {
|
||||
namespace audit_log {
|
||||
|
||||
|
||||
AuditLog::AuditLog()
|
||||
: m_path1(""),
|
||||
m_path2(""),
|
||||
m_storage_dir(""),
|
||||
m_format(NotSetAuditLogFormat),
|
||||
m_parts(-1),
|
||||
m_filePermission(-1),
|
||||
m_directoryPermission(-1),
|
||||
m_status(NotSetLogStatus),
|
||||
m_type(NotSetAuditLogType),
|
||||
m_relevant(""),
|
||||
m_writer(NULL),
|
||||
m_ctlAuditEngineActive(false) { }
|
||||
AuditLog::AuditLog() = default;
|
||||
|
||||
|
||||
AuditLog::~AuditLog() {
|
||||
if (m_writer) {
|
||||
delete m_writer;
|
||||
m_writer = NULL;
|
||||
m_writer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,35 +96,42 @@ bool AuditLog::setStatus(AuditLogStatus status) {
|
||||
}
|
||||
|
||||
|
||||
bool AuditLog::setRelevantStatus(const std::basic_string<char>& status) {
|
||||
bool AuditLog::setRelevantStatus(std::string_view status) {
|
||||
this->m_relevant = std::string(status);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool AuditLog::setStorageDir(const std::basic_string<char>& path) {
|
||||
bool AuditLog::setStorageDir(std::string_view path) {
|
||||
this->m_storage_dir = path;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool AuditLog::setFilePath1(const std::basic_string<char>& path) {
|
||||
bool AuditLog::setFilePath1(std::string_view path) {
|
||||
this->m_path1 = path;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool AuditLog::setFilePath2(const std::basic_string<char>& path) {
|
||||
bool AuditLog::setFilePath2(std::string_view path) {
|
||||
this->m_path2 = path;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool AuditLog::setPrefix(std::string_view prefix) {
|
||||
this->m_prefix = prefix;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool AuditLog::setFormat(AuditLogFormat fmt) {
|
||||
this->m_format = fmt;
|
||||
return true;
|
||||
}
|
||||
|
||||
int AuditLog::addParts(int parts, const std::string& new_parts) {
|
||||
int AuditLog::addParts(int parts, std::string_view new_parts) {
|
||||
PARTS_CONSTAINS('A', AAuditLogPart)
|
||||
PARTS_CONSTAINS('B', BAuditLogPart)
|
||||
PARTS_CONSTAINS('C', CAuditLogPart)
|
||||
@ -154,7 +149,7 @@ int AuditLog::addParts(int parts, const std::string& new_parts) {
|
||||
}
|
||||
|
||||
|
||||
int AuditLog::removeParts(int parts, const std::string& new_parts) {
|
||||
int AuditLog::removeParts(int parts, std::string_view new_parts) {
|
||||
PARTS_CONSTAINS_REM('A', AAuditLogPart)
|
||||
PARTS_CONSTAINS_REM('B', BAuditLogPart)
|
||||
PARTS_CONSTAINS_REM('C', CAuditLogPart)
|
||||
@ -172,7 +167,7 @@ int AuditLog::removeParts(int parts, const std::string& new_parts) {
|
||||
}
|
||||
|
||||
|
||||
bool AuditLog::setParts(const std::basic_string<char>& new_parts) {
|
||||
bool AuditLog::setParts(std::string_view new_parts) {
|
||||
int parts = 0;
|
||||
|
||||
PARTS_CONSTAINS('A', AAuditLogPart)
|
||||
@ -208,7 +203,6 @@ bool AuditLog::setType(AuditLogType audit_type) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool AuditLog::init(std::string *error) {
|
||||
audit_log::writer::Writer *tmp_writer;
|
||||
|
||||
@ -216,7 +210,7 @@ bool AuditLog::init(std::string *error) {
|
||||
&& !m_ctlAuditEngineActive) {
|
||||
if (m_writer) {
|
||||
delete m_writer;
|
||||
m_writer = NULL;
|
||||
m_writer = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -234,7 +228,7 @@ bool AuditLog::init(std::string *error) {
|
||||
tmp_writer = new audit_log::writer::Serial(this);
|
||||
}
|
||||
|
||||
if (tmp_writer == NULL) {
|
||||
if (tmp_writer == nullptr) {
|
||||
error->assign("Writer memory alloc failed!");
|
||||
return false;
|
||||
}
|
||||
@ -312,7 +306,7 @@ bool AuditLog::saveIfRelevant(Transaction *transaction, int parts) {
|
||||
}
|
||||
ms_dbg_a(transaction, 5, "Saving this request as part " \
|
||||
"of the audit logs.");
|
||||
if (m_writer == NULL) {
|
||||
if (m_writer == nullptr) {
|
||||
ms_dbg_a(transaction, 1, "Internal error, audit log writer is null");
|
||||
} else {
|
||||
std::string error;
|
||||
@ -337,6 +331,7 @@ bool AuditLog::merge(AuditLog *from, std::string *error) {
|
||||
AL_MERGE_STRING_CONF(from->m_path2, m_path2);
|
||||
AL_MERGE_STRING_CONF(from->m_storage_dir, m_storage_dir);
|
||||
AL_MERGE_STRING_CONF(from->m_relevant, m_relevant);
|
||||
AL_MERGE_STRING_CONF(from->m_prefix, m_prefix);
|
||||
|
||||
if (from->m_filePermission != -1) {
|
||||
m_filePermission = from->m_filePermission;
|
||||
|
@ -119,7 +119,7 @@ bool Parallel::write(Transaction *transaction, int parts, std::string *error) {
|
||||
} else {
|
||||
std::string boundary;
|
||||
generateBoundary(&boundary);
|
||||
log = transaction->toOldAuditLogFormat(parts, "-" + boundary + "--");
|
||||
log = transaction->toOldAuditLogFormat(parts, "-" + boundary + "--", m_audit->m_prefix);
|
||||
}
|
||||
|
||||
const auto &logPath = m_audit->m_storage_dir;
|
||||
|
@ -42,7 +42,7 @@ bool Serial::write(Transaction *transaction, int parts, std::string *error) {
|
||||
} else {
|
||||
std::string boundary;
|
||||
generateBoundary(&boundary);
|
||||
msg = transaction->toOldAuditLogFormat(parts, "-" + boundary + "--");
|
||||
msg = transaction->toOldAuditLogFormat(parts, "-" + boundary + "--", m_audit->m_prefix);
|
||||
}
|
||||
|
||||
return utils::SharedFiles::getInstance().write(m_audit->m_path1, msg,
|
||||
|
@ -27,8 +27,8 @@ bool FuzzyHash::init(const std::string ¶m2, std::string *error) {
|
||||
#ifdef WITH_SSDEEP
|
||||
std::string digit;
|
||||
std::string file;
|
||||
std::istream *iss;
|
||||
struct fuzzy_hash_chunk *chunk, *t;
|
||||
std::ifstream *iss;
|
||||
std::shared_ptr<fuzzy_hash_chunk> chunk, t;
|
||||
std::string err;
|
||||
|
||||
auto pos = m_param.find_last_of(' ');
|
||||
@ -48,18 +48,17 @@ bool FuzzyHash::init(const std::string ¶m2, std::string *error) {
|
||||
std::string resource = utils::find_resource(file, param2, &err);
|
||||
iss = new std::ifstream(resource, std::ios::in);
|
||||
|
||||
if (((std::ifstream *)iss)->is_open() == false) {
|
||||
if (iss->is_open() == false) {
|
||||
error->assign("Failed to open file: " + m_param + ". " + err);
|
||||
delete iss;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (std::string line; std::getline(*iss, line); ) {
|
||||
chunk = (struct fuzzy_hash_chunk *)calloc(1,
|
||||
sizeof(struct fuzzy_hash_chunk));
|
||||
chunk = std::make_shared<fuzzy_hash_chunk>();
|
||||
|
||||
chunk->data = strdup(line.c_str());
|
||||
chunk->next = NULL;
|
||||
chunk->data = std::shared_ptr<char>(strdup(line.c_str()), free);
|
||||
chunk->next = nullptr;
|
||||
|
||||
if (m_head == NULL) {
|
||||
m_head = chunk;
|
||||
@ -83,23 +82,11 @@ bool FuzzyHash::init(const std::string ¶m2, std::string *error) {
|
||||
#endif
|
||||
}
|
||||
|
||||
FuzzyHash::~FuzzyHash() {
|
||||
struct fuzzy_hash_chunk *c = m_head;
|
||||
while (c) {
|
||||
struct fuzzy_hash_chunk *t = c;
|
||||
free(c->data);
|
||||
c->data = NULL;
|
||||
c = c->next;
|
||||
free(t);
|
||||
}
|
||||
m_head = NULL;
|
||||
}
|
||||
|
||||
|
||||
bool FuzzyHash::evaluate(Transaction *t, const std::string &str) {
|
||||
#ifdef WITH_SSDEEP
|
||||
char result[FUZZY_MAX_RESULT];
|
||||
struct fuzzy_hash_chunk *chunk = m_head;
|
||||
std::shared_ptr<fuzzy_hash_chunk> chunk = m_head;
|
||||
|
||||
|
||||
if (fuzzy_hash_buf((const unsigned char*)str.c_str(),
|
||||
str.size(), result)) {
|
||||
@ -108,7 +95,7 @@ bool FuzzyHash::evaluate(Transaction *t, const std::string &str) {
|
||||
}
|
||||
|
||||
while (chunk != NULL) {
|
||||
int i = fuzzy_compare(chunk->data, result);
|
||||
int i = fuzzy_compare(chunk->data.get(), result);
|
||||
if (i >= m_threshold) {
|
||||
ms_dbg_a(t, 4, "Fuzzy hash: matched " \
|
||||
"with score: " + std::to_string(i) + ".");
|
||||
|
@ -31,8 +31,8 @@ namespace operators {
|
||||
|
||||
|
||||
struct fuzzy_hash_chunk {
|
||||
char *data;
|
||||
struct fuzzy_hash_chunk *next;
|
||||
std::shared_ptr<char> data;
|
||||
std::shared_ptr<fuzzy_hash_chunk> next;
|
||||
};
|
||||
|
||||
class FuzzyHash : public Operator {
|
||||
@ -42,14 +42,14 @@ class FuzzyHash : public Operator {
|
||||
: Operator("FuzzyHash", std::move(param)),
|
||||
m_threshold(0),
|
||||
m_head(NULL) { }
|
||||
~FuzzyHash() override;
|
||||
~FuzzyHash() override = default;
|
||||
|
||||
bool evaluate(Transaction *transaction, const std::string &std) override;
|
||||
|
||||
bool init(const std::string ¶m, std::string *error) override;
|
||||
private:
|
||||
int m_threshold;
|
||||
struct fuzzy_hash_chunk *m_head;
|
||||
std::shared_ptr<fuzzy_hash_chunk> m_head;
|
||||
};
|
||||
|
||||
} // namespace operators
|
||||
|
@ -31,14 +31,14 @@ namespace modsecurity {
|
||||
namespace operators {
|
||||
|
||||
bool InspectFile::init(const std::string ¶m2, std::string *error) {
|
||||
std::istream *iss;
|
||||
std::ifstream *iss;
|
||||
std::string err;
|
||||
std::string err_lua;
|
||||
|
||||
m_file = utils::find_resource(m_param, param2, &err);
|
||||
iss = new std::ifstream(m_file, std::ios::in);
|
||||
|
||||
if (((std::ifstream *)iss)->is_open() == false) {
|
||||
if (iss->is_open() == false) {
|
||||
error->assign("Failed to open file: " + m_param + ". " + err);
|
||||
delete iss;
|
||||
return false;
|
||||
|
@ -20,7 +20,9 @@
|
||||
#include "src/operators/operator.h"
|
||||
#include "src/utils/https_client.h"
|
||||
#include "src/utils/system.h"
|
||||
#include "src/utils/string.h"
|
||||
|
||||
using namespace modsecurity::utils::string;
|
||||
|
||||
namespace modsecurity {
|
||||
namespace operators {
|
||||
@ -44,39 +46,44 @@ bool PmFromFile::isComment(const std::string &s) {
|
||||
}
|
||||
|
||||
bool PmFromFile::init(const std::string &config, std::string *error) {
|
||||
std::istream *iss;
|
||||
std::vector<std::string> tokens = split(m_param, ' ');
|
||||
|
||||
if (m_param.compare(0, 8, "https://") == 0) {
|
||||
Utils::HttpsClient client;
|
||||
bool ret = client.download(m_param);
|
||||
if (ret == false) {
|
||||
error->assign(client.error);
|
||||
return false;
|
||||
for (const auto& token : tokens) {
|
||||
if (token.empty()) {
|
||||
continue;
|
||||
}
|
||||
iss = new std::stringstream(client.content);
|
||||
} else {
|
||||
std::string err;
|
||||
std::string resource = utils::find_resource(m_param, config, &err);
|
||||
iss = new std::ifstream(resource, std::ios::in);
|
||||
|
||||
if (((std::ifstream *)iss)->is_open() == false) {
|
||||
error->assign("Failed to open file: " + m_param + ". " + err);
|
||||
delete iss;
|
||||
return false;
|
||||
std::unique_ptr<std::istream> iss;
|
||||
|
||||
if (token.compare(0, 8, "https://") == 0) {
|
||||
Utils::HttpsClient client;
|
||||
bool ret = client.download(token);
|
||||
if (ret == false) {
|
||||
error->assign(client.error);
|
||||
return false;
|
||||
}
|
||||
iss = std::make_unique<std::stringstream>(client.content);
|
||||
} else {
|
||||
std::string err;
|
||||
std::string resource = utils::find_resource(token, config, &err);
|
||||
auto file = std::make_unique<std::ifstream>(resource, std::ios::in);
|
||||
if (file->is_open() == false) {
|
||||
error->assign("Failed to open file: '" + token + "'. " + err);
|
||||
return false;
|
||||
}
|
||||
iss = std::move(file);
|
||||
}
|
||||
for (std::string line; std::getline(*iss, line); ) {
|
||||
if (isComment(line) == false) {
|
||||
acmp_add_pattern(m_p, line.c_str(), NULL, NULL, line.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::string line; std::getline(*iss, line); ) {
|
||||
if (isComment(line) == false) {
|
||||
acmp_add_pattern(m_p, line.c_str(), NULL, NULL, line.length());
|
||||
}
|
||||
}
|
||||
|
||||
while (m_p->is_failtree_done == 0) {
|
||||
acmp_prepare(m_p);
|
||||
}
|
||||
|
||||
delete iss;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -226,9 +226,20 @@ bool Rbl::evaluate(Transaction *t, RuleWithActions *rule,
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sockaddr *addr = info->ai_addr;
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *) addr;
|
||||
furtherInfo(sin, ipStr, t, m_provider);
|
||||
// SonarCloud suggested to use the init-statement to declare "addr" inside the if statement.
|
||||
// I think that's not good here, because we need that in the else block
|
||||
const struct sockaddr *addr = info->ai_addr; // NOSONAR
|
||||
if (addr->sa_family == AF_INET) { // NOSONAR
|
||||
struct sockaddr_in sin{}; // initialize an empty struct; we don't need port info
|
||||
memcpy(&sin.sin_addr, addr->sa_data + 2, sizeof(sin.sin_addr));
|
||||
sin.sin_family = AF_INET;
|
||||
furtherInfo(&sin, ipStr, t, m_provider);
|
||||
}
|
||||
else {
|
||||
ms_dbg_a(t, 7, "Unsupported address family: " + std::to_string(addr->sa_family));
|
||||
freeaddrinfo(info);
|
||||
return false;
|
||||
}
|
||||
|
||||
freeaddrinfo(info);
|
||||
if (rule && t && rule->hasCaptureAction()) {
|
||||
|
@ -68,19 +68,20 @@ bool Rx::evaluate(Transaction *transaction, RuleWithActions *rule,
|
||||
|
||||
// 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);
|
||||
if (transaction) {
|
||||
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");
|
||||
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 + "'");
|
||||
}
|
||||
|
||||
ms_dbg_a(transaction, 1, "rx: regex error '" + regex_error_str + "' for pattern '" + re->pattern + "'");
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -62,18 +62,20 @@ bool RxGlobal::evaluate(Transaction *transaction, RuleWithActions *rule,
|
||||
|
||||
// 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);
|
||||
if (transaction) {
|
||||
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");
|
||||
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 + "'");
|
||||
}
|
||||
|
||||
ms_dbg_a(transaction, 1, "rxGlobal: regex error '" + regex_error_str + "' for pattern '" + re->pattern + "'");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ bool ValidateDTD::init(const std::string &file, std::string *error) {
|
||||
|
||||
bool ValidateDTD::evaluate(Transaction *transaction, const std::string &str) {
|
||||
|
||||
XmlDtdPtrManager dtd(xmlParseDTD(NULL, (const xmlChar *)m_resource.c_str()));
|
||||
XmlDtdPtrManager dtd(xmlParseDTD(NULL, reinterpret_cast<const xmlChar *>(m_resource.c_str())));
|
||||
if (dtd.get() == NULL) {
|
||||
std::string err = std::string("XML: Failed to load DTD: ") \
|
||||
+ m_resource;
|
||||
|
@ -21,11 +21,11 @@
|
||||
|
||||
#include "src/operators/operator.h"
|
||||
|
||||
#ifndef WITH_PCRE2
|
||||
#ifdef WITH_PCRE
|
||||
#if PCRE_HAVE_JIT
|
||||
#define pcre_study_opt PCRE_STUDY_JIT_COMPILE
|
||||
#else
|
||||
#define pcre_study_opt 0
|
||||
constexpr int pcre_study_opt = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -34,20 +34,20 @@ namespace modsecurity {
|
||||
namespace operators {
|
||||
|
||||
VerifyCC::~VerifyCC() {
|
||||
#if WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
pcre2_code_free(m_pc);
|
||||
#else
|
||||
if (m_pc != NULL) {
|
||||
if (m_pc != nullptr) {
|
||||
pcre_free(m_pc);
|
||||
m_pc = NULL;
|
||||
m_pc = nullptr;
|
||||
}
|
||||
if (m_pce != NULL) {
|
||||
if (m_pce != nullptr) {
|
||||
#if PCRE_HAVE_JIT
|
||||
pcre_free_study(m_pce);
|
||||
#else
|
||||
pcre_free(m_pce);
|
||||
#endif
|
||||
m_pce = NULL;
|
||||
m_pce = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -94,33 +94,33 @@ int VerifyCC::luhnVerify(const char *ccnumber, int len) {
|
||||
|
||||
|
||||
bool VerifyCC::init(const std::string ¶m2, std::string *error) {
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
PCRE2_SPTR pcre2_pattern = reinterpret_cast<PCRE2_SPTR>(m_param.c_str());
|
||||
uint32_t pcre2_options = (PCRE2_DOTALL|PCRE2_MULTILINE);
|
||||
int errornumber = 0;
|
||||
PCRE2_SIZE erroroffset = 0;
|
||||
m_pc = pcre2_compile(pcre2_pattern, PCRE2_ZERO_TERMINATED,
|
||||
pcre2_options, &errornumber, &erroroffset, NULL);
|
||||
if (m_pc == NULL) {
|
||||
pcre2_options, &errornumber, &erroroffset, nullptr);
|
||||
if (m_pc == nullptr) {
|
||||
return false;
|
||||
}
|
||||
m_pcje = pcre2_jit_compile(m_pc, PCRE2_JIT_COMPLETE);
|
||||
#else
|
||||
const char *errptr = NULL;
|
||||
const char *errptr = nullptr;
|
||||
int erroffset = 0;
|
||||
|
||||
m_pc = pcre_compile(m_param.c_str(), PCRE_DOTALL|PCRE_MULTILINE,
|
||||
&errptr, &erroffset, NULL);
|
||||
if (m_pc == NULL) {
|
||||
&errptr, &erroffset, nullptr);
|
||||
if (m_pc == nullptr) {
|
||||
error->assign(errptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pce = pcre_study(m_pc, pcre_study_opt, &errptr);
|
||||
if (m_pce == NULL) {
|
||||
if (errptr == NULL) {
|
||||
if (m_pce == nullptr) {
|
||||
if (errptr == nullptr) {
|
||||
/*
|
||||
* Per pcre_study(3) m_pce == NULL && errptr == NULL means
|
||||
* Per pcre_study(3) m_pce == nullptr && errptr == nullptr means
|
||||
* that no addional information is found, so no need to study
|
||||
*/
|
||||
return true;
|
||||
@ -136,21 +136,21 @@ bool VerifyCC::init(const std::string ¶m2, std::string *error) {
|
||||
|
||||
bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule,
|
||||
const std::string& i, RuleMessage &ruleMessage) {
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
PCRE2_SIZE offset = 0;
|
||||
size_t target_length = i.length();
|
||||
PCRE2_SPTR pcre2_i = reinterpret_cast<PCRE2_SPTR>(i.c_str());
|
||||
pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_pc, NULL);
|
||||
pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_pc, nullptr);
|
||||
|
||||
int ret;
|
||||
for (offset = 0; offset < target_length; offset++) {
|
||||
|
||||
if (m_pcje == 0) {
|
||||
ret = pcre2_jit_match(m_pc, pcre2_i, target_length, offset, 0, match_data, NULL);
|
||||
ret = pcre2_jit_match(m_pc, pcre2_i, target_length, offset, 0, match_data, nullptr);
|
||||
}
|
||||
|
||||
if (m_pcje != 0 || ret == PCRE2_ERROR_JIT_STACKLIMIT) {
|
||||
ret = pcre2_match(m_pc, pcre2_i, target_length, offset, PCRE2_NO_JIT, match_data, NULL);
|
||||
ret = pcre2_match(m_pc, pcre2_i, target_length, offset, PCRE2_NO_JIT, match_data, nullptr);
|
||||
}
|
||||
|
||||
/* If there was no match, then we are done. */
|
||||
@ -192,7 +192,7 @@ bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule,
|
||||
"\" at " + i + ". [offset " +
|
||||
std::to_string(offset) + "]");
|
||||
}
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
pcre2_match_data_free(match_data);
|
||||
#endif
|
||||
return true;
|
||||
@ -200,7 +200,7 @@ bool VerifyCC::evaluate(Transaction *t, RuleWithActions *rule,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
pcre2_match_data_free(match_data);
|
||||
#endif
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
#ifndef SRC_OPERATORS_VERIFY_CC_H_
|
||||
#define SRC_OPERATORS_VERIFY_CC_H_
|
||||
|
||||
#if WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
#define PCRE2_CODE_UNIT_WIDTH 8
|
||||
#include <pcre2.h>
|
||||
#else
|
||||
@ -38,12 +38,12 @@ class VerifyCC : public Operator {
|
||||
/** @ingroup ModSecurity_Operator */
|
||||
explicit VerifyCC(std::unique_ptr<RunTimeString> param)
|
||||
: Operator("VerifyCC", std::move(param)),
|
||||
#if WITH_PCRE2
|
||||
m_pc(NULL),
|
||||
#ifndef WITH_PCRE
|
||||
m_pc(nullptr),
|
||||
m_pcje(PCRE2_ERROR_JIT_BADOPTION) { }
|
||||
#else
|
||||
m_pc(NULL),
|
||||
m_pce(NULL) { }
|
||||
m_pc(nullptr),
|
||||
m_pce(nullptr) { }
|
||||
#endif
|
||||
~VerifyCC() override;
|
||||
|
||||
@ -52,7 +52,7 @@ class VerifyCC : public Operator {
|
||||
RuleMessage &ruleMessage) override;
|
||||
bool init(const std::string ¶m, std::string *error) override;
|
||||
private:
|
||||
#if WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
pcre2_code *m_pc;
|
||||
int m_pcje;
|
||||
#else
|
||||
|
@ -25,6 +25,7 @@ libmodsec_parser_la_CPPFLAGS = \
|
||||
$(YAJL_CFLAGS) \
|
||||
$(LMDB_CFLAGS) \
|
||||
$(PCRE_CFLAGS) \
|
||||
$(PCRE2_CFLAGS) \
|
||||
$(LIBXML2_CFLAGS)
|
||||
|
||||
test.cc: seclang-parser.hh
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -27,6 +27,7 @@ class Driver;
|
||||
#include "src/actions/chain.h"
|
||||
#include "src/actions/ctl/audit_engine.h"
|
||||
#include "src/actions/ctl/audit_log_parts.h"
|
||||
#include "src/actions/ctl/parse_xml_into_args.h"
|
||||
#include "src/actions/ctl/request_body_access.h"
|
||||
#include "src/actions/ctl/rule_engine.h"
|
||||
#include "src/actions/ctl/request_body_processor_json.h"
|
||||
@ -478,7 +479,7 @@ using namespace modsecurity::operators;
|
||||
OPERATOR_VERIFY_CC "OPERATOR_VERIFY_CC"
|
||||
OPERATOR_VERIFY_CPF "OPERATOR_VERIFY_CPF"
|
||||
OPERATOR_VERIFY_SSN "OPERATOR_VERIFY_SSN"
|
||||
OPERATOR_VERIFY_SVNR "OPERATOR_VERIFY_SVNR"
|
||||
OPERATOR_VERIFY_SVNR "OPERATOR_VERIFY_SVNR"
|
||||
OPERATOR_WITHIN "OPERATOR_WITHIN"
|
||||
|
||||
CONFIG_DIR_AUDIT_LOG_FMT
|
||||
@ -502,6 +503,7 @@ using namespace modsecurity::operators;
|
||||
ACTION_CTL_BDY_XML "ACTION_CTL_BDY_XML"
|
||||
ACTION_CTL_BDY_URLENCODED "ACTION_CTL_BDY_URLENCODED"
|
||||
ACTION_CTL_FORCE_REQ_BODY_VAR "ACTION_CTL_FORCE_REQ_BODY_VAR"
|
||||
ACTION_CTL_PARSE_XML_INTO_ARGS "ACTION_CTL_PARSE_XML_INTO_ARGS"
|
||||
ACTION_CTL_REQUEST_BODY_ACCESS "ACTION_CTL_REQUEST_BODY_ACCESS"
|
||||
ACTION_CTL_RULE_REMOVE_BY_ID "ACTION_CTL_RULE_REMOVE_BY_ID"
|
||||
ACTION_CTL_RULE_REMOVE_BY_TAG "ACTION_CTL_RULE_REMOVE_BY_TAG"
|
||||
@ -593,6 +595,7 @@ using namespace modsecurity::operators;
|
||||
CONFIG_DIR_AUDIT_LOG2 "CONFIG_DIR_AUDIT_LOG2"
|
||||
CONFIG_DIR_AUDIT_LOG_P "CONFIG_DIR_AUDIT_LOG_P"
|
||||
CONFIG_DIR_AUDIT_STS "CONFIG_DIR_AUDIT_STS"
|
||||
CONFIG_DIR_AUDIT_PREFIX "CONFIG_DIR_AUDIT_PREFIX"
|
||||
CONFIG_DIR_AUDIT_TPE "CONFIG_DIR_AUDIT_TPE"
|
||||
CONFIG_DIR_DEBUG_LOG "CONFIG_DIR_DEBUG_LOG"
|
||||
CONFIG_DIR_DEBUG_LVL "CONFIG_DIR_DEBUG_LVL"
|
||||
@ -649,6 +652,7 @@ using namespace modsecurity::operators;
|
||||
CONFIG_VALUE_ABORT "CONFIG_VALUE_ABORT"
|
||||
CONFIG_VALUE_DETC "CONFIG_VALUE_DETC"
|
||||
CONFIG_VALUE_HTTPS "CONFIG_VALUE_HTTPS"
|
||||
CONFIG_VALUE_ONLYARGS "CONFIG_VALUE_ONLYARGS"
|
||||
CONFIG_VALUE_OFF "CONFIG_VALUE_OFF"
|
||||
CONFIG_VALUE_ON "CONFIG_VALUE_ON"
|
||||
CONFIG_VALUE_PARALLEL "CONFIG_VALUE_PARALLEL"
|
||||
@ -658,6 +662,7 @@ using namespace modsecurity::operators;
|
||||
CONFIG_VALUE_SERIAL "CONFIG_VALUE_SERIAL"
|
||||
CONFIG_VALUE_WARN "CONFIG_VALUE_WARN"
|
||||
CONFIG_XML_EXTERNAL_ENTITY "CONFIG_XML_EXTERNAL_ENTITY"
|
||||
CONFIG_XML_PARSE_XML_INTO_ARGS "CONFIG_XML_PARSE_XML_INTO_ARGS"
|
||||
CONGIG_DIR_RESPONSE_BODY_MP "CONGIG_DIR_RESPONSE_BODY_MP"
|
||||
CONGIG_DIR_SEC_ARG_SEP "CONGIG_DIR_SEC_ARG_SEP"
|
||||
CONGIG_DIR_SEC_COOKIE_FORMAT "CONGIG_DIR_SEC_COOKIE_FORMAT"
|
||||
@ -797,6 +802,13 @@ audit_log:
|
||||
driver.m_auditLog->setRelevantStatus(relevant_status);
|
||||
}
|
||||
|
||||
/* SecAuditLogPrefix */
|
||||
| CONFIG_DIR_AUDIT_PREFIX
|
||||
{
|
||||
std::string prefix($1);
|
||||
driver.m_auditLog->setPrefix(prefix);
|
||||
}
|
||||
|
||||
/* SecAuditLogType */
|
||||
| CONFIG_DIR_AUDIT_TPE CONFIG_VALUE_SERIAL
|
||||
{
|
||||
@ -827,13 +839,19 @@ audit_log:
|
||||
}
|
||||
| CONFIG_UPLOAD_FILE_LIMIT
|
||||
{
|
||||
driver.m_uploadFileLimit.m_set = true;
|
||||
driver.m_uploadFileLimit.m_value = strtol($1.c_str(), NULL, 10);
|
||||
std::string errmsg = "";
|
||||
if (driver.m_uploadFileLimit.parse(std::string($1), &errmsg) != true) {
|
||||
driver.error(@0, "Failed to parse SecUploadFileLimit: " + errmsg);
|
||||
YYERROR;
|
||||
}
|
||||
}
|
||||
| CONFIG_UPLOAD_FILE_MODE
|
||||
{
|
||||
driver.m_uploadFileMode.m_set = true;
|
||||
driver.m_uploadFileMode.m_value = strtol($1.c_str(), NULL, 8);
|
||||
std::string errmsg = "";
|
||||
if (driver.m_uploadFileMode.parse(std::string($1), &errmsg) != true) {
|
||||
driver.error(@0, "Failed to parse SecUploadFileMode: " + errmsg);
|
||||
YYERROR;
|
||||
}
|
||||
}
|
||||
| CONFIG_UPLOAD_DIR
|
||||
{
|
||||
@ -1604,13 +1622,19 @@ expression:
|
||||
/* Body limits */
|
||||
| CONFIG_DIR_REQ_BODY_LIMIT
|
||||
{
|
||||
driver.m_requestBodyLimit.m_set = true;
|
||||
driver.m_requestBodyLimit.m_value = atoi($1.c_str());
|
||||
std::string errmsg = "";
|
||||
if (driver.m_requestBodyLimit.parse(std::string($1), &errmsg) != true) {
|
||||
driver.error(@0, "Failed to parse SecRequestBodyLimit: " + errmsg);
|
||||
YYERROR;
|
||||
}
|
||||
}
|
||||
| CONFIG_DIR_REQ_BODY_NO_FILES_LIMIT
|
||||
{
|
||||
driver.m_requestBodyNoFilesLimit.m_set = true;
|
||||
driver.m_requestBodyNoFilesLimit.m_value = atoi($1.c_str());
|
||||
std::string errmsg = "";
|
||||
if (driver.m_requestBodyNoFilesLimit.parse(std::string($1), &errmsg) != true) {
|
||||
driver.error(@0, "Failed to parse SecRequestsBodyNoFilesLimit: " + errmsg);
|
||||
YYERROR;
|
||||
}
|
||||
}
|
||||
| CONFIG_DIR_REQ_BODY_IN_MEMORY_LIMIT
|
||||
{
|
||||
@ -1623,8 +1647,11 @@ expression:
|
||||
}
|
||||
| CONFIG_DIR_RES_BODY_LIMIT
|
||||
{
|
||||
driver.m_responseBodyLimit.m_set = true;
|
||||
driver.m_responseBodyLimit.m_value = atoi($1.c_str());
|
||||
std::string errmsg = "";
|
||||
if (driver.m_responseBodyLimit.parse(std::string($1), &errmsg) != true) {
|
||||
driver.error(@0, "Failed to parse SecResponseBodyLimit: " + errmsg);
|
||||
YYERROR;
|
||||
}
|
||||
}
|
||||
| CONFIG_DIR_REQ_BODY_LIMIT_ACTION CONFIG_VALUE_PROCESS_PARTIAL
|
||||
{
|
||||
@ -1657,8 +1684,11 @@ expression:
|
||||
*/
|
||||
| CONFIG_DIR_PCRE_MATCH_LIMIT
|
||||
{
|
||||
driver.m_pcreMatchLimit.m_set = true;
|
||||
driver.m_pcreMatchLimit.m_value = atoi($1.c_str());
|
||||
std::string errmsg = "";
|
||||
if (driver.m_pcreMatchLimit.parse(std::string($1), &errmsg) != true) {
|
||||
driver.error(@0, "Failed to parse SecPcreMatchLimit: " + errmsg);
|
||||
YYERROR;
|
||||
}
|
||||
}
|
||||
| CONGIG_DIR_RESPONSE_BODY_MP
|
||||
{
|
||||
@ -1686,6 +1716,18 @@ expression:
|
||||
{
|
||||
driver.m_secXMLExternalEntity = modsecurity::RulesSetProperties::TrueConfigBoolean;
|
||||
}
|
||||
| CONFIG_XML_PARSE_XML_INTO_ARGS CONFIG_VALUE_ONLYARGS
|
||||
{
|
||||
driver.m_secXMLParseXmlIntoArgs = modsecurity::RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs;
|
||||
}
|
||||
| CONFIG_XML_PARSE_XML_INTO_ARGS CONFIG_VALUE_OFF
|
||||
{
|
||||
driver.m_secXMLParseXmlIntoArgs = modsecurity::RulesSetProperties::FalseConfigXMLParseXmlIntoArgs;
|
||||
}
|
||||
| CONFIG_XML_PARSE_XML_INTO_ARGS CONFIG_VALUE_ON
|
||||
{
|
||||
driver.m_secXMLParseXmlIntoArgs = modsecurity::RulesSetProperties::TrueConfigXMLParseXmlIntoArgs;
|
||||
}
|
||||
| CONGIG_DIR_SEC_TMP_DIR
|
||||
{
|
||||
/* Parser error disabled to avoid breaking default installations with modsecurity.conf-recommended
|
||||
@ -2696,6 +2738,18 @@ act:
|
||||
//ACTION_NOT_SUPPORTED("CtlForceReequestBody", @0);
|
||||
ACTION_CONTAINER($$, new actions::Action($1));
|
||||
}
|
||||
| ACTION_CTL_PARSE_XML_INTO_ARGS CONFIG_VALUE_ON
|
||||
{
|
||||
ACTION_CONTAINER($$, new actions::ctl::ParseXmlIntoArgs("ctl:parseXmlIntoArgs=on"));
|
||||
}
|
||||
| ACTION_CTL_PARSE_XML_INTO_ARGS CONFIG_VALUE_OFF
|
||||
{
|
||||
ACTION_CONTAINER($$, new actions::ctl::ParseXmlIntoArgs("ctl:parseXmlIntoArgs=off"));
|
||||
}
|
||||
| ACTION_CTL_PARSE_XML_INTO_ARGS CONFIG_VALUE_ONLYARGS
|
||||
{
|
||||
ACTION_CONTAINER($$, new actions::ctl::ParseXmlIntoArgs("ctl:parseXmlIntoArgs=onlyargs"));
|
||||
}
|
||||
| ACTION_CTL_REQUEST_BODY_ACCESS CONFIG_VALUE_ON
|
||||
{
|
||||
ACTION_CONTAINER($$, new actions::ctl::RequestBodyAccess($1 + "true"));
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -90,6 +90,7 @@ ACTION_CTL_BDY_JSON (?i:ctl:requestBodyProcessor=JSO
|
||||
ACTION_CTL_BDY_XML (?i:ctl:requestBodyProcessor=XML)
|
||||
ACTION_CTL_BDY_URLENCODED (?i:ctl:requestBodyProcessor=URLENCODED)
|
||||
ACTION_CTL_FORCE_REQ_BODY_VAR (?i:ctl:forceRequestBodyVariable)
|
||||
ACTION_CTL_PARSE_XML_INTO_ARGS (?i:ctl:parseXmlIntoArgs)
|
||||
ACTION_CTL_REQUEST_BODY_ACCESS (?i:ctl:requestBodyAccess)
|
||||
ACTION_CTL_RULE_ENGINE (?i:ctl:ruleEngine)
|
||||
ACTION_CTL_RULE_REMOVE_BY_TAG (?i:ctl:ruleRemoveByTag)
|
||||
@ -345,6 +346,7 @@ CONFIG_DIR_AUDIT_FLE_MOD (?i:SecAuditLogFileMode)
|
||||
CONFIG_DIR_AUDIT_LOG2 (?i:SecAuditLog2)
|
||||
CONFIG_DIR_AUDIT_LOG (?i:SecAuditLog)
|
||||
CONFIG_DIR_AUDIT_LOG_FMT (?i:SecAuditLogFormat)
|
||||
CONFIG_DIR_AUDIT_PREFIX (?i:SecAuditLogPrefix)
|
||||
CONFIG_DIR_AUDIT_LOG_P (?i:SecAuditLogParts)
|
||||
CONFIG_DIR_AUDIT_STS (?i:SecAuditLogRelevantStatus)
|
||||
CONFIG_DIR_AUDIT_TPE (?i:SecAuditLogType)
|
||||
@ -400,16 +402,18 @@ CONFIG_VALUE_ABORT (?i:Abort)
|
||||
CONFIG_VALUE_DETC (?i:DetectionOnly)
|
||||
CONFIG_VALUE_HTTPS (?i:https)
|
||||
CONFIG_VALUE_NUMBER [0-9]+
|
||||
CONFIG_VALUE_ONLYARGS (?i:OnlyArgs)
|
||||
CONFIG_VALUE_OFF (?i:Off)
|
||||
CONFIG_VALUE_ON (?i:On)
|
||||
CONFIG_VALUE_PARALLEL (?i:Parallel|Concurrent)
|
||||
CONFIG_VALUE_PATH [0-9A-Za-z_\/\.\-\*\:]+
|
||||
CONFIG_VALUE_PATH (?i:[0-9a-z_/.*: \\()-]+)
|
||||
CONFIG_VALUE_PROCESS_PARTIAL (?i:ProcessPartial)
|
||||
CONFIG_VALUE_REJECT (?i:Reject)
|
||||
CONFIG_VALUE_RELEVANT_ONLY (?i:RelevantOnly)
|
||||
CONFIG_VALUE_SERIAL (?i:Serial)
|
||||
CONFIG_VALUE_WARN (?i:Warn)
|
||||
CONFIG_XML_EXTERNAL_ENTITY (?i:SecXmlExternalEntity)
|
||||
CONFIG_XML_PARSE_XML_INTO_ARGS (?i:SecParseXmlIntoArgs)
|
||||
CONGIG_DIR_RESPONSE_BODY_MP (?i:SecResponseBodyMimeType)
|
||||
CONGIG_DIR_RESPONSE_BODY_MP_CLEAR (?i:SecResponseBodyMimeTypesClear)
|
||||
CONGIG_DIR_SEC_ARG_SEP (?i:SecArgumentSeparator)
|
||||
@ -537,6 +541,7 @@ EQUALS_MINUS (?i:=\-)
|
||||
{ACTION_CTL_BDY_XML} { return p::make_ACTION_CTL_BDY_XML(yytext, *driver.loc.back()); }
|
||||
{ACTION_CTL_BDY_URLENCODED} { return p::make_ACTION_CTL_BDY_URLENCODED(yytext, *driver.loc.back()); }
|
||||
{ACTION_CTL_FORCE_REQ_BODY_VAR}= { return p::make_ACTION_CTL_FORCE_REQ_BODY_VAR(yytext, *driver.loc.back()); }
|
||||
{ACTION_CTL_PARSE_XML_INTO_ARGS}= { return p::make_ACTION_CTL_PARSE_XML_INTO_ARGS(yytext, *driver.loc.back()); }
|
||||
{ACTION_CTL_REQUEST_BODY_ACCESS}= { return p::make_ACTION_CTL_REQUEST_BODY_ACCESS(yytext, *driver.loc.back()); }
|
||||
{ACTION_CTL_RULE_ENGINE}= { return p::make_ACTION_CTL_RULE_ENGINE(*driver.loc.back()); }
|
||||
{ACTION_CTL_RULE_REMOVE_BY_ID}[=]{REMOVE_RULE_BY} { return p::make_ACTION_CTL_RULE_REMOVE_BY_ID(yytext, *driver.loc.back()); }
|
||||
@ -609,6 +614,7 @@ EQUALS_MINUS (?i:=\-)
|
||||
{ACTION_LOG_DATA}: { BEGIN(EXPECTING_ACTION_PREDICATE); return p::make_ACTION_LOG_DATA(yytext, *driver.loc.back()); }
|
||||
|
||||
{CONFIG_VALUE_DETC} { return p::make_CONFIG_VALUE_DETC(yytext, *driver.loc.back()); }
|
||||
{CONFIG_VALUE_ONLYARGS} { return p::make_CONFIG_VALUE_ONLYARGS(yytext, *driver.loc.back()); }
|
||||
{CONFIG_VALUE_OFF} { return p::make_CONFIG_VALUE_OFF(yytext, *driver.loc.back()); }
|
||||
{CONFIG_VALUE_ON} { return p::make_CONFIG_VALUE_ON(yytext, *driver.loc.back()); }
|
||||
{CONFIG_VALUE_RELEVANT_ONLY} { return p::make_CONFIG_VALUE_RELEVANT_ONLY(yytext, *driver.loc.back()); }
|
||||
@ -759,6 +765,8 @@ EQUALS_MINUS (?i:=\-)
|
||||
{CONFIG_DIR_AUDIT_LOG}[ \t]+["]{CONFIG_VALUE_PATH}["] { return p::make_CONFIG_DIR_AUDIT_LOG(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }
|
||||
{CONFIG_DIR_AUDIT_STS}[ \t]+{FREE_TEXT_NEW_LINE} { return p::make_CONFIG_DIR_AUDIT_STS(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }
|
||||
{CONFIG_DIR_AUDIT_STS}[ \t]+["]{NEW_LINE_FREE_TEXT}["] { return p::make_CONFIG_DIR_AUDIT_STS(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }
|
||||
{CONFIG_DIR_AUDIT_PREFIX}[ \t]+{FREE_TEXT_NEW_LINE} { return p::make_CONFIG_DIR_AUDIT_PREFIX(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }
|
||||
{CONFIG_DIR_AUDIT_PREFIX}[ \t]+["]{FREE_TEXT_NEW_LINE}["] { return p::make_CONFIG_DIR_AUDIT_PREFIX(parserSanitizer(strchr(yytext, ' ') + 1), *driver.loc.back()); }
|
||||
{CONFIG_DIR_AUDIT_TPE} { return p::make_CONFIG_DIR_AUDIT_TPE(yytext, *driver.loc.back()); }
|
||||
|
||||
|
||||
@ -805,6 +813,7 @@ EQUALS_MINUS (?i:=\-)
|
||||
{CONFIG_VALUE_ABORT} { return p::make_CONFIG_VALUE_ABORT(yytext, *driver.loc.back()); }
|
||||
{CONFIG_VALUE_DETC} { return p::make_CONFIG_VALUE_DETC(yytext, *driver.loc.back()); }
|
||||
{CONFIG_VALUE_HTTPS} { return p::make_CONFIG_VALUE_HTTPS(yytext, *driver.loc.back()); }
|
||||
{CONFIG_VALUE_ONLYARGS} { return p::make_CONFIG_VALUE_ONLYARGS(yytext, *driver.loc.back()); }
|
||||
{CONFIG_VALUE_OFF} { return p::make_CONFIG_VALUE_OFF(yytext, *driver.loc.back()); }
|
||||
{CONFIG_VALUE_ON} { return p::make_CONFIG_VALUE_ON(yytext, *driver.loc.back()); }
|
||||
{CONFIG_VALUE_PARALLEL} { return p::make_CONFIG_VALUE_PARALLEL(yytext, *driver.loc.back()); }
|
||||
@ -814,6 +823,7 @@ EQUALS_MINUS (?i:=\-)
|
||||
{CONFIG_VALUE_SERIAL} { return p::make_CONFIG_VALUE_SERIAL(yytext, *driver.loc.back()); }
|
||||
{CONFIG_VALUE_WARN} { return p::make_CONFIG_VALUE_WARN(yytext, *driver.loc.back()); }
|
||||
{CONFIG_XML_EXTERNAL_ENTITY} { return p::make_CONFIG_XML_EXTERNAL_ENTITY(yytext, *driver.loc.back()); }
|
||||
{CONFIG_XML_PARSE_XML_INTO_ARGS} { return p::make_CONFIG_XML_PARSE_XML_INTO_ARGS(yytext, *driver.loc.back()); }
|
||||
{CONGIG_DIR_RESPONSE_BODY_MP}[ \t]+{FREE_TEXT_NEW_LINE} { return p::make_CONGIG_DIR_RESPONSE_BODY_MP(strchr(yytext, ' ') + 1, *driver.loc.back()); }
|
||||
{CONGIG_DIR_RESPONSE_BODY_MP_CLEAR} { return p::make_CONGIG_DIR_RESPONSE_BODY_MP_CLEAR(*driver.loc.back()); }
|
||||
{CONGIG_DIR_SEC_ARG_SEP}[ \t]+{FREE_TEXT_NEW_LINE} { return p::make_CONGIG_DIR_SEC_ARG_SEP(yytext, *driver.loc.back()); }
|
||||
|
@ -1638,7 +1638,7 @@ bool Multipart::process(const std::string& data, std::string *error,
|
||||
}
|
||||
} else { /* It looks like a boundary but */
|
||||
/* we couldn't match it. */
|
||||
char *p = NULL;
|
||||
const char *p = NULL;
|
||||
|
||||
/* Check if an attempt to use quotes around the
|
||||
* boundary was made. */
|
||||
|
@ -25,11 +25,138 @@ namespace RequestBodyProcessor {
|
||||
|
||||
#ifdef WITH_LIBXML2
|
||||
|
||||
/*
|
||||
* NodeData for parsing XML into args
|
||||
*/
|
||||
NodeData::NodeData() {
|
||||
has_child = false;
|
||||
}
|
||||
|
||||
NodeData::~NodeData() {};
|
||||
|
||||
/*
|
||||
* XMLNodes for parsing XML into args
|
||||
*/
|
||||
XMLNodes::XMLNodes(Transaction *transaction)
|
||||
: nodes{},
|
||||
node_depth(0),
|
||||
currpath(""),
|
||||
currval(""),
|
||||
currval_is_set(false),
|
||||
m_transaction(transaction)
|
||||
{}
|
||||
|
||||
XMLNodes::~XMLNodes() {};
|
||||
|
||||
/*
|
||||
* SAX handler for parsing XML into args
|
||||
*/
|
||||
class MSCSAXHandler {
|
||||
public:
|
||||
void onStartElement(void * ctx, const xmlChar *localname) {
|
||||
|
||||
std::string name = reinterpret_cast<const char*>(localname);
|
||||
|
||||
XMLNodes* xml_data = static_cast<XMLNodes*>(ctx);
|
||||
xml_data->nodes.push_back(std::make_shared<NodeData>());
|
||||
xml_data->node_depth++;
|
||||
// FIXME - later if we want to check the depth of XML tree
|
||||
/* if (max_depth > 0 && max_depth > xml_data->node_depth) {
|
||||
std::cout << "Depth of XML tree reached the given maximum value " << xml_data->node_depth << std::endl;
|
||||
exit(1);
|
||||
} */
|
||||
// if it's not the first (root) item, then append a '.'
|
||||
// note, the condition should always be true because there is always a pseudo root element: 'xml'
|
||||
if (xml_data->nodes.size() > 1) {
|
||||
xml_data->currpath.append(".");
|
||||
xml_data->nodes[xml_data->nodes.size()-2]->has_child = true;
|
||||
}
|
||||
xml_data->currpath.append(name);
|
||||
// set the current value empty
|
||||
// this is necessary because if there is any text between the tags (new line, etc)
|
||||
// it will be added to the current value
|
||||
xml_data->currval = "";
|
||||
xml_data->currval_is_set = false;
|
||||
}
|
||||
|
||||
void onEndElement(void * ctx, const xmlChar *localname) {
|
||||
std::string name = reinterpret_cast<const char*>(localname);
|
||||
XMLNodes* xml_data = static_cast<XMLNodes*>(ctx);
|
||||
const std::shared_ptr<NodeData>& nd = xml_data->nodes[xml_data->nodes.size()-1];
|
||||
if (nd->has_child == false) {
|
||||
// check the return value
|
||||
// if false, then stop parsing
|
||||
// this means the number of arguments reached the limit
|
||||
if (xml_data->m_transaction->addArgument("XML", xml_data->currpath, xml_data->currval, 0) == false) {
|
||||
xmlStopParser(xml_data->parsing_ctx_arg);
|
||||
}
|
||||
}
|
||||
if (xml_data->currpath.length() > 0) {
|
||||
// set an offset to store whether this is the first item, in order to know whether to remove the '.'
|
||||
int offset = (xml_data->nodes.size() > 1) ? 1 : 0;
|
||||
xml_data->currpath.erase(xml_data->currpath.length() - (name.length()+offset));
|
||||
}
|
||||
xml_data->nodes.pop_back();
|
||||
xml_data->node_depth--;
|
||||
xml_data->currval = "";
|
||||
xml_data->currval_is_set = false;
|
||||
}
|
||||
|
||||
void onCharacters(void *ctx, const xmlChar *ch, int len) {
|
||||
XMLNodes* xml_data = static_cast<XMLNodes*>(ctx);
|
||||
std::string content(reinterpret_cast<const char *>(ch), len);
|
||||
|
||||
// libxml2 SAX parser will call this function multiple times
|
||||
// during the parsing of a single node, if the value has multibyte
|
||||
// characters, so we need to concatenate the values
|
||||
if (xml_data->currval_is_set == false) {
|
||||
xml_data->currval = content;
|
||||
xml_data->currval_is_set = true;
|
||||
} else {
|
||||
xml_data->currval += content;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
void MSC_startElement(void *userData,
|
||||
const xmlChar *name,
|
||||
const xmlChar *prefix,
|
||||
const xmlChar *URI,
|
||||
int nb_namespaces,
|
||||
const xmlChar **namespaces,
|
||||
int nb_attributes,
|
||||
int nb_defaulted,
|
||||
const xmlChar **attributes) {
|
||||
|
||||
MSCSAXHandler* handler = static_cast<MSCSAXHandler*>(userData);
|
||||
handler->onStartElement(userData, name);
|
||||
}
|
||||
|
||||
void MSC_endElement(
|
||||
void *userData,
|
||||
const xmlChar *name,
|
||||
const xmlChar* prefix,
|
||||
const xmlChar* URI) {
|
||||
|
||||
MSCSAXHandler* handler = static_cast<MSCSAXHandler*>(userData);
|
||||
handler->onEndElement(userData, name);
|
||||
}
|
||||
|
||||
void MSC_xmlcharacters(void *userData, const xmlChar *ch, int len) {
|
||||
MSCSAXHandler* handler = static_cast<MSCSAXHandler*>(userData);
|
||||
handler->onCharacters(userData, ch, len);
|
||||
}
|
||||
}
|
||||
|
||||
XML::XML(Transaction *transaction)
|
||||
: m_transaction(transaction) {
|
||||
m_data.doc = NULL;
|
||||
m_data.parsing_ctx = NULL;
|
||||
m_data.sax_handler = NULL;
|
||||
m_data.xml_error = "";
|
||||
m_data.parsing_ctx_arg = NULL;
|
||||
m_data.xml_parser_state = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -44,7 +171,6 @@ XML::~XML() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool XML::init() {
|
||||
//xmlParserInputBufferCreateFilenameFunc entity;
|
||||
if (m_transaction->m_rules->m_secXMLExternalEntity
|
||||
@ -55,6 +181,28 @@ bool XML::init() {
|
||||
/*entity = */xmlParserInputBufferCreateFilenameDefault(
|
||||
this->unloadExternalEntity);
|
||||
}
|
||||
if (m_transaction->m_secXMLParseXmlIntoArgs
|
||||
== RulesSetProperties::TrueConfigXMLParseXmlIntoArgs ||
|
||||
m_transaction->m_secXMLParseXmlIntoArgs
|
||||
== RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs) {
|
||||
ms_dbg_a(m_transaction, 9,
|
||||
"XML: SecParseXmlIntoArgs is set to " \
|
||||
+ RulesSetProperties::configXMLParseXmlIntoArgsString(static_cast<RulesSetProperties::ConfigXMLParseXmlIntoArgs>(m_transaction->m_secXMLParseXmlIntoArgs)));
|
||||
m_data.sax_handler = std::make_unique<xmlSAXHandler>();
|
||||
memset(m_data.sax_handler.get(), 0, sizeof(xmlSAXHandler));
|
||||
|
||||
m_data.sax_handler->initialized = XML_SAX2_MAGIC;
|
||||
m_data.sax_handler->startElementNs = &MSC_startElement;
|
||||
m_data.sax_handler->endElementNs = &MSC_endElement;
|
||||
m_data.sax_handler->characters = &MSC_xmlcharacters;
|
||||
|
||||
// set the parser state struct
|
||||
m_data.xml_parser_state = std::make_unique<XMLNodes>(m_transaction);
|
||||
m_data.xml_parser_state->node_depth = 0;
|
||||
m_data.xml_parser_state->currval = "";
|
||||
// the XML will contain at least one node, which is the pseudo root node 'xml'
|
||||
m_data.xml_parser_state->currpath = "xml.";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -72,7 +220,7 @@ bool XML::processChunk(const char *buf, unsigned int size,
|
||||
* enable us to pass it the first chunk of data so that
|
||||
* it can attempt to auto-detect the encoding.
|
||||
*/
|
||||
if (m_data.parsing_ctx == NULL) {
|
||||
if (m_data.parsing_ctx == NULL && m_data.parsing_ctx_arg == NULL) {
|
||||
/* First invocation. */
|
||||
|
||||
ms_dbg_a(m_transaction, 4, "XML: Initialising parser.");
|
||||
@ -90,27 +238,67 @@ bool XML::processChunk(const char *buf, unsigned int size,
|
||||
|
||||
*/
|
||||
|
||||
m_data.parsing_ctx = xmlCreatePushParserCtxt(NULL, NULL,
|
||||
buf, size, "body.xml");
|
||||
if (m_transaction->m_secXMLParseXmlIntoArgs
|
||||
!= RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs) {
|
||||
m_data.parsing_ctx = xmlCreatePushParserCtxt(NULL, NULL,
|
||||
buf, size, "body.xml");
|
||||
|
||||
if (m_data.parsing_ctx == NULL) {
|
||||
ms_dbg_a(m_transaction, 4,
|
||||
"XML: Failed to create parsing context.");
|
||||
error->assign("XML: Failed to create parsing context.");
|
||||
return false;
|
||||
if (m_data.parsing_ctx == NULL) {
|
||||
ms_dbg_a(m_transaction, 4,
|
||||
"XML: Failed to create parsing context.");
|
||||
error->assign("XML: Failed to create parsing context.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
xmlSetGenericErrorFunc(m_data.parsing_ctx, null_error);
|
||||
if (m_transaction->m_secXMLParseXmlIntoArgs
|
||||
== RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs ||
|
||||
m_transaction->m_secXMLParseXmlIntoArgs
|
||||
== RulesSetProperties::TrueConfigXMLParseXmlIntoArgs) {
|
||||
m_data.parsing_ctx_arg = xmlCreatePushParserCtxt(
|
||||
m_data.sax_handler.get(),
|
||||
m_data.xml_parser_state.get(),
|
||||
buf,
|
||||
size,
|
||||
NULL);
|
||||
if (m_data.parsing_ctx_arg == NULL) {
|
||||
error->assign("XML: Failed to create parsing context for ARGS.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Not a first invocation. */
|
||||
xmlParseChunk(m_data.parsing_ctx, buf, size, 0);
|
||||
if (m_data.parsing_ctx->wellFormed != 1) {
|
||||
error->assign("XML: Failed to create parsing context.");
|
||||
ms_dbg_a(m_transaction, 4, "XML: Failed parsing document.");
|
||||
return false;
|
||||
if (m_data.parsing_ctx != NULL &&
|
||||
m_transaction->m_secXMLParseXmlIntoArgs
|
||||
!= RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs) {
|
||||
xmlSetGenericErrorFunc(m_data.parsing_ctx, null_error);
|
||||
xmlParseChunk(m_data.parsing_ctx, buf, size, 0);
|
||||
m_data.xml_parser_state->parsing_ctx_arg = m_data.parsing_ctx_arg;
|
||||
if (m_data.parsing_ctx->wellFormed != 1) {
|
||||
error->assign("XML: Failed to parse document.");
|
||||
ms_dbg_a(m_transaction, 4, "XML: Failed to parse document.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_data.parsing_ctx_arg != NULL &&
|
||||
(
|
||||
m_transaction->m_secXMLParseXmlIntoArgs
|
||||
== RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs
|
||||
||
|
||||
m_transaction->m_secXMLParseXmlIntoArgs
|
||||
== RulesSetProperties::TrueConfigXMLParseXmlIntoArgs)
|
||||
) {
|
||||
xmlSetGenericErrorFunc(m_data.parsing_ctx_arg, null_error);
|
||||
xmlParseChunk(m_data.parsing_ctx_arg, buf, size, 0);
|
||||
if (m_data.parsing_ctx_arg->wellFormed != 1) {
|
||||
error->assign("XML: Failed to parse document for ARGS.");
|
||||
ms_dbg_a(m_transaction, 4, "XML: Failed to parse document for ARGS.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -119,24 +307,51 @@ bool XML::processChunk(const char *buf, unsigned int size,
|
||||
|
||||
bool XML::complete(std::string *error) {
|
||||
/* Only if we have a context, meaning we've done some work. */
|
||||
if (m_data.parsing_ctx != NULL) {
|
||||
/* This is how we signalise the end of parsing to libxml. */
|
||||
xmlParseChunk(m_data.parsing_ctx, NULL, 0, 1);
|
||||
if (m_data.parsing_ctx != NULL || m_data.parsing_ctx_arg != NULL) {
|
||||
if (m_data.parsing_ctx != NULL &&
|
||||
m_transaction->m_secXMLParseXmlIntoArgs
|
||||
!= RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs) {
|
||||
/* This is how we signal the end of parsing to libxml. */
|
||||
xmlParseChunk(m_data.parsing_ctx, NULL, 0, 1);
|
||||
|
||||
/* Preserve the results for our reference. */
|
||||
m_data.well_formed = m_data.parsing_ctx->wellFormed;
|
||||
m_data.doc = m_data.parsing_ctx->myDoc;
|
||||
/* Preserve the results for our reference. */
|
||||
m_data.well_formed = m_data.parsing_ctx->wellFormed;
|
||||
m_data.doc = m_data.parsing_ctx->myDoc;
|
||||
|
||||
/* Clean up everything else. */
|
||||
xmlFreeParserCtxt(m_data.parsing_ctx);
|
||||
m_data.parsing_ctx = NULL;
|
||||
ms_dbg_a(m_transaction, 4, "XML: Parsing complete (well_formed " \
|
||||
+ std::to_string(m_data.well_formed) + ").");
|
||||
/* Clean up everything else. */
|
||||
xmlFreeParserCtxt(m_data.parsing_ctx);
|
||||
m_data.parsing_ctx = NULL;
|
||||
ms_dbg_a(m_transaction, 4, "XML: Parsing complete (well_formed " \
|
||||
+ std::to_string(m_data.well_formed) + ").");
|
||||
|
||||
if (m_data.well_formed != 1) {
|
||||
error->assign("XML: Failed parsing document.");
|
||||
ms_dbg_a(m_transaction, 4, "XML: Failed parsing document.");
|
||||
return false;
|
||||
if (m_data.well_formed != 1) {
|
||||
error->assign("XML: Failed to parse document.");
|
||||
ms_dbg_a(m_transaction, 4, "XML: Failed to parse document.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (m_data.parsing_ctx_arg != NULL &&
|
||||
(
|
||||
m_transaction->m_secXMLParseXmlIntoArgs
|
||||
== RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs
|
||||
||
|
||||
m_transaction->m_secXMLParseXmlIntoArgs
|
||||
== RulesSetProperties::TrueConfigXMLParseXmlIntoArgs)
|
||||
) {
|
||||
/* This is how we signale the end of parsing to libxml. */
|
||||
if (xmlParseChunk(m_data.parsing_ctx_arg, NULL, 0, 1) != 0) {
|
||||
if (m_data.xml_error != "") {
|
||||
error->assign(m_data.xml_error);
|
||||
}
|
||||
else {
|
||||
error->assign("XML: Failed to parse document for ARGS.");
|
||||
}
|
||||
xmlFreeParserCtxt(m_data.parsing_ctx_arg);
|
||||
m_data.parsing_ctx_arg = NULL;
|
||||
return false;
|
||||
}
|
||||
xmlFreeParserCtxt(m_data.parsing_ctx_arg);
|
||||
m_data.parsing_ctx_arg = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#ifdef WITH_LIBXML2
|
||||
#include <libxml/xmlschemas.h>
|
||||
#include <libxml/xpath.h>
|
||||
#include <libxml/SAX.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
@ -33,12 +34,51 @@ namespace RequestBodyProcessor {
|
||||
|
||||
#ifdef WITH_LIBXML2
|
||||
|
||||
/*
|
||||
* NodeData for parsing XML into args
|
||||
*/
|
||||
class NodeData {
|
||||
public:
|
||||
explicit NodeData();
|
||||
~NodeData();
|
||||
|
||||
bool has_child;
|
||||
};
|
||||
|
||||
/*
|
||||
* XMLNodes for parsing XML into args
|
||||
*/
|
||||
class XMLNodes {
|
||||
public:
|
||||
std::vector<std::shared_ptr<NodeData>> nodes;
|
||||
unsigned long int node_depth;
|
||||
std::string currpath;
|
||||
std::string currval;
|
||||
bool currval_is_set;
|
||||
Transaction *m_transaction;
|
||||
// need to store context - this is the same as in xml_data
|
||||
// need to stop parsing if the number of arguments reached the limit
|
||||
xmlParserCtxtPtr parsing_ctx_arg;
|
||||
|
||||
explicit XMLNodes (Transaction *);
|
||||
~XMLNodes();
|
||||
};
|
||||
|
||||
struct xml_data {
|
||||
xmlSAXHandler *sax_handler;
|
||||
std::unique_ptr<xmlSAXHandler> sax_handler;
|
||||
xmlParserCtxtPtr parsing_ctx;
|
||||
xmlDocPtr doc;
|
||||
|
||||
unsigned int well_formed;
|
||||
|
||||
/* error reporting and XML array flag */
|
||||
std::string xml_error;
|
||||
|
||||
/* additional parser context for arguments */
|
||||
xmlParserCtxtPtr parsing_ctx_arg;
|
||||
|
||||
/* parser state for SAX parser */
|
||||
std::unique_ptr<XMLNodes> xml_parser_state;
|
||||
};
|
||||
|
||||
typedef struct xml_data xml_data;
|
||||
|
@ -90,17 +90,6 @@ void RuleWithOperator::updateMatchedVars(Transaction *trans, const std::string &
|
||||
}
|
||||
|
||||
|
||||
void RuleWithOperator::cleanMatchedVars(Transaction *trans) {
|
||||
ms_dbg_a(trans, 9, "Matched vars cleaned.");
|
||||
// cppcheck-suppress ctunullpointer
|
||||
trans->m_variableMatchedVar.unset();
|
||||
trans->m_variableMatchedVars.unset();
|
||||
trans->m_variableMatchedVarName.unset();
|
||||
trans->m_variableMatchedVarsNames.unset();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool RuleWithOperator::executeOperatorAt(Transaction *trans, const std::string &key,
|
||||
const std::string &value, RuleMessage &ruleMessage) {
|
||||
#if MSC_EXEC_CLOCK_ENABLED
|
||||
@ -324,7 +313,6 @@ bool RuleWithOperator::evaluate(Transaction *trans,
|
||||
|
||||
if (globalRet == false) {
|
||||
ms_dbg_a(trans, 4, "Rule returned 0.");
|
||||
cleanMatchedVars(trans);
|
||||
goto end_clean;
|
||||
}
|
||||
ms_dbg_a(trans, 4, "Rule returned 1.");
|
||||
|
@ -58,7 +58,7 @@ bool RulesExceptions::loadUpdateActionById(double id,
|
||||
|
||||
|
||||
bool RulesExceptions::loadRemoveRuleByMsg(const std::string &msg,
|
||||
std::string *error) {
|
||||
const std::string *error) {
|
||||
m_remove_rule_by_msg.push_back(msg);
|
||||
|
||||
return true;
|
||||
@ -66,7 +66,7 @@ bool RulesExceptions::loadRemoveRuleByMsg(const std::string &msg,
|
||||
|
||||
|
||||
bool RulesExceptions::loadRemoveRuleByTag(const std::string &msg,
|
||||
std::string *error) {
|
||||
const std::string *error) {
|
||||
m_remove_rule_by_tag.push_back(msg);
|
||||
|
||||
return true;
|
||||
|
@ -105,6 +105,14 @@ std::string RulesSet::getParserError() {
|
||||
return this->m_parserError.str();
|
||||
}
|
||||
|
||||
void RulesSet::cleanMatchedVars(Transaction *trans) {
|
||||
ms_dbg_a(trans, 9, "Matched vars cleaned.");
|
||||
// cppcheck-suppress ctunullpointer
|
||||
trans->m_variableMatchedVar.unset();
|
||||
trans->m_variableMatchedVars.unset();
|
||||
trans->m_variableMatchedVarName.unset();
|
||||
trans->m_variableMatchedVarsNames.unset();
|
||||
}
|
||||
|
||||
int RulesSet::evaluate(int phase, Transaction *t) {
|
||||
if (phase >= modsecurity::Phases::NUMBER_OF_PHASES) {
|
||||
@ -208,6 +216,7 @@ int RulesSet::evaluate(int phase, Transaction *t) {
|
||||
}
|
||||
|
||||
rule->evaluate(t);
|
||||
cleanMatchedVars(t);
|
||||
if (t->m_it.disruptive > 0) {
|
||||
|
||||
ms_dbg_a(t, 8, "Skipping this phase as this " \
|
||||
|
@ -148,6 +148,7 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, const char *id,
|
||||
m_json(nullptr),
|
||||
#endif
|
||||
m_secRuleEngine(RulesSetProperties::PropertyNotSetRuleEngine),
|
||||
m_secXMLParseXmlIntoArgs(rules->m_secXMLParseXmlIntoArgs),
|
||||
m_logCbData(logCbData),
|
||||
TransactionAnchoredVariables(this) {
|
||||
m_variableUrlEncodedError.set("0", 0);
|
||||
@ -1451,7 +1452,7 @@ std::string Transaction::toOldAuditLogFormatIndex(const std::string &filename,
|
||||
|
||||
|
||||
std::string Transaction::toOldAuditLogFormat(int parts,
|
||||
const std::string &trailer) {
|
||||
const std::string &trailer, const std::string &prefix) {
|
||||
std::stringstream audit_log;
|
||||
|
||||
struct tm timeinfo;
|
||||
@ -1460,7 +1461,8 @@ std::string Transaction::toOldAuditLogFormat(int parts,
|
||||
char tstr[std::size("[dd/Mmm/yyyy:hh:mm:ss shhmm]")];
|
||||
strftime(tstr, std::size(tstr), "[%d/%b/%Y:%H:%M:%S %z]", &timeinfo);
|
||||
|
||||
audit_log << "--" << trailer << "-" << "A--" << std::endl;
|
||||
audit_log << prefix << "--" << trailer << "-" << "A--" << std::endl;
|
||||
audit_log << prefix;
|
||||
audit_log << tstr;
|
||||
audit_log << " " << m_id;
|
||||
audit_log << " " << this->m_clientIpAddress;
|
||||
@ -1471,7 +1473,8 @@ std::string Transaction::toOldAuditLogFormat(int parts,
|
||||
|
||||
if (parts & audit_log::AuditLog::BAuditLogPart) {
|
||||
std::vector<const VariableValue *> l;
|
||||
audit_log << "--" << trailer << "-" << "B--" << std::endl;
|
||||
audit_log << prefix << "--" << trailer << "-" << "B--" << std::endl;
|
||||
audit_log << prefix;
|
||||
audit_log << utils::string::dash_if_empty(
|
||||
m_variableRequestMethod.evaluate());
|
||||
audit_log << " " << this->m_uri.c_str() << " " << "HTTP/";
|
||||
@ -1480,79 +1483,81 @@ std::string Transaction::toOldAuditLogFormat(int parts,
|
||||
m_variableRequestHeaders.resolve(&l);
|
||||
for (auto &h : l) {
|
||||
size_t pos = strlen("REQUEST_HEADERS:");
|
||||
audit_log << prefix;
|
||||
audit_log << h->getKeyWithCollection().c_str() + pos << ": ";
|
||||
audit_log << h->getValue().c_str() << std::endl;
|
||||
delete h;
|
||||
}
|
||||
audit_log << std::endl;
|
||||
audit_log << prefix << std::endl;
|
||||
}
|
||||
if (parts & audit_log::AuditLog::CAuditLogPart
|
||||
&& m_requestBody.tellp() > 0) {
|
||||
std::string body = m_requestBody.str();
|
||||
audit_log << "--" << trailer << "-" << "C--" << std::endl;
|
||||
audit_log << prefix << "--" << trailer << "-" << "C--" << std::endl;
|
||||
if (body.size() > 0) {
|
||||
audit_log << body << std::endl;
|
||||
audit_log << prefix << body << std::endl;
|
||||
}
|
||||
audit_log << std::endl;
|
||||
audit_log << prefix << std::endl;
|
||||
}
|
||||
if (parts & audit_log::AuditLog::DAuditLogPart) {
|
||||
audit_log << "--" << trailer << "-" << "D--" << std::endl;
|
||||
audit_log << std::endl;
|
||||
audit_log << prefix << "--" << trailer << "-" << "D--" << std::endl;
|
||||
audit_log << prefix << std::endl;
|
||||
/** TODO: write audit_log D part. */
|
||||
}
|
||||
if (parts & audit_log::AuditLog::EAuditLogPart
|
||||
&& m_responseBody.tellp() > 0) {
|
||||
std::string body = utils::string::toHexIfNeeded(m_responseBody.str());
|
||||
audit_log << "--" << trailer << "-" << "E--" << std::endl;
|
||||
audit_log << prefix << "--" << trailer << "-" << "E--" << std::endl;
|
||||
if (body.size() > 0) {
|
||||
audit_log << body << std::endl;
|
||||
audit_log << prefix << body << std::endl;
|
||||
}
|
||||
audit_log << std::endl;
|
||||
audit_log << prefix << std::endl;
|
||||
}
|
||||
if (parts & audit_log::AuditLog::FAuditLogPart) {
|
||||
std::vector<const VariableValue *> l;
|
||||
|
||||
audit_log << "--" << trailer << "-" << "F--" << std::endl;
|
||||
audit_log << "HTTP/" << m_httpVersion.c_str() << " ";
|
||||
audit_log << prefix << "--" << trailer << "-" << "F--" << std::endl;
|
||||
audit_log << prefix << "HTTP/" << m_httpVersion.c_str() << " ";
|
||||
audit_log << this->m_httpCodeReturned << std::endl;
|
||||
m_variableResponseHeaders.resolve(&l);
|
||||
for (auto &h : l) {
|
||||
audit_log << prefix;
|
||||
audit_log << h->getKey().c_str() << ": ";
|
||||
audit_log << h->getValue().c_str() << std::endl;
|
||||
delete h;
|
||||
}
|
||||
}
|
||||
audit_log << std::endl;
|
||||
audit_log << prefix << std::endl;
|
||||
|
||||
if (parts & audit_log::AuditLog::GAuditLogPart) {
|
||||
audit_log << "--" << trailer << "-" << "G--" << std::endl;
|
||||
audit_log << prefix << "--" << trailer << "-" << "G--" << std::endl;
|
||||
audit_log << std::endl;
|
||||
/** TODO: write audit_log G part. */
|
||||
}
|
||||
if (parts & audit_log::AuditLog::HAuditLogPart) {
|
||||
audit_log << "--" << trailer << "-" << "H--" << std::endl;
|
||||
audit_log << prefix << "--" << trailer << "-" << "H--" << std::endl;
|
||||
for (const auto &a : m_rulesMessages) {
|
||||
audit_log << a.log(0, m_httpCodeReturned) << std::endl;
|
||||
audit_log << prefix << a.log(0, m_httpCodeReturned) << std::endl;
|
||||
}
|
||||
audit_log << std::endl;
|
||||
audit_log << prefix << std::endl;
|
||||
/** TODO: write audit_log H part. */
|
||||
}
|
||||
if (parts & audit_log::AuditLog::IAuditLogPart) {
|
||||
audit_log << "--" << trailer << "-" << "I--" << std::endl;
|
||||
audit_log << std::endl;
|
||||
audit_log << prefix << "--" << trailer << "-" << "I--" << std::endl;
|
||||
audit_log << prefix << std::endl;
|
||||
/** TODO: write audit_log I part. */
|
||||
}
|
||||
if (parts & audit_log::AuditLog::JAuditLogPart) {
|
||||
audit_log << "--" << trailer << "-" << "J--" << std::endl;
|
||||
audit_log << std::endl;
|
||||
audit_log << prefix << "--" << trailer << "-" << "J--" << std::endl;
|
||||
audit_log << prefix << std::endl;
|
||||
/** TODO: write audit_log J part. */
|
||||
}
|
||||
if (parts & audit_log::AuditLog::KAuditLogPart) {
|
||||
audit_log << "--" << trailer << "-" << "K--" << std::endl;
|
||||
audit_log << std::endl;
|
||||
audit_log << prefix << "--" << trailer << "-" << "K--" << std::endl;
|
||||
audit_log << prefix << std::endl;
|
||||
/** TODO: write audit_log K part. */
|
||||
}
|
||||
audit_log << "--" << trailer << "-" << "Z--" << std::endl << std::endl;
|
||||
audit_log << prefix << "--" << trailer << "-" << "Z--" << std::endl << std::endl;
|
||||
|
||||
return audit_log.str();
|
||||
}
|
||||
@ -1564,7 +1569,7 @@ std::string Transaction::toJSON(int parts) {
|
||||
size_t len;
|
||||
yajl_gen g;
|
||||
std::string log;
|
||||
std::string ts = utils::string::ascTime(&m_timeStamp).c_str();
|
||||
std::string ts = utils::string::ascTime(&m_timeStamp);
|
||||
std::string uniqueId = UniqueId::uniqueId();
|
||||
|
||||
g = yajl_gen_alloc(NULL);
|
||||
@ -1582,13 +1587,13 @@ std::string Transaction::toJSON(int parts) {
|
||||
|
||||
yajl_gen_map_open(g);
|
||||
/* Part: A (header mandatory) */
|
||||
LOGFY_ADD("client_ip", m_clientIpAddress.c_str());
|
||||
LOGFY_ADD("time_stamp", ts.c_str());
|
||||
LOGFY_ADD("server_id", uniqueId.c_str());
|
||||
LOGFY_ADD("client_ip", m_clientIpAddress);
|
||||
LOGFY_ADD("time_stamp", ts);
|
||||
LOGFY_ADD("server_id", uniqueId);
|
||||
LOGFY_ADD_NUM("client_port", m_clientPort);
|
||||
LOGFY_ADD("host_ip", m_serverIpAddress.c_str());
|
||||
LOGFY_ADD("host_ip", m_serverIpAddress);
|
||||
LOGFY_ADD_NUM("host_port", m_serverPort);
|
||||
LOGFY_ADD("unique_id", m_id.c_str());
|
||||
LOGFY_ADD("unique_id", m_id);
|
||||
|
||||
/* request */
|
||||
yajl_gen_string(g, reinterpret_cast<const unsigned char*>("request"),
|
||||
@ -1597,14 +1602,15 @@ std::string Transaction::toJSON(int parts) {
|
||||
|
||||
LOGFY_ADD("method",
|
||||
utils::string::dash_if_empty(
|
||||
m_variableRequestMethod.evaluate()).c_str());
|
||||
m_variableRequestMethod.evaluate()));
|
||||
|
||||
LOGFY_ADD_INT("http_version", m_httpVersion.c_str());
|
||||
LOGFY_ADD("uri", this->m_uri.c_str());
|
||||
LOGFY_ADD("http_version", m_httpVersion);
|
||||
LOGFY_ADD("hostname", m_requestHostName);
|
||||
LOGFY_ADD("uri", this->m_uri);
|
||||
|
||||
if (parts & audit_log::AuditLog::CAuditLogPart) {
|
||||
// FIXME: check for the binary content size.
|
||||
LOGFY_ADD("body", this->m_requestBody.str().c_str());
|
||||
LOGFY_ADD("body", this->m_requestBody.str());
|
||||
}
|
||||
|
||||
/* request headers */
|
||||
@ -1616,7 +1622,7 @@ std::string Transaction::toJSON(int parts) {
|
||||
|
||||
m_variableRequestHeaders.resolve(&l);
|
||||
for (auto &h : l) {
|
||||
LOGFY_ADD(h->getKey().c_str(), h->getValue().c_str());
|
||||
LOGFY_ADD(h->getKey().c_str(), h->getValue());
|
||||
delete h;
|
||||
}
|
||||
|
||||
@ -1633,7 +1639,7 @@ std::string Transaction::toJSON(int parts) {
|
||||
yajl_gen_map_open(g);
|
||||
|
||||
if (parts & audit_log::AuditLog::EAuditLogPart) {
|
||||
LOGFY_ADD("body", this->m_responseBody.str().c_str());
|
||||
LOGFY_ADD("body", this->m_responseBody.str());
|
||||
}
|
||||
LOGFY_ADD_NUM("http_code", m_httpCodeReturned);
|
||||
|
||||
@ -1646,7 +1652,7 @@ std::string Transaction::toJSON(int parts) {
|
||||
|
||||
m_variableResponseHeaders.resolve(&l);
|
||||
for (auto &h : l) {
|
||||
LOGFY_ADD(h->getKey().c_str(), h->getValue().c_str());
|
||||
LOGFY_ADD(h->getKey().c_str(), h->getValue());
|
||||
delete h;
|
||||
}
|
||||
|
||||
@ -1663,10 +1669,10 @@ std::string Transaction::toJSON(int parts) {
|
||||
yajl_gen_map_open(g);
|
||||
|
||||
/* producer > libmodsecurity */
|
||||
LOGFY_ADD("modsecurity", m_ms->whoAmI().c_str());
|
||||
LOGFY_ADD("modsecurity", m_ms->whoAmI());
|
||||
|
||||
/* producer > connector */
|
||||
LOGFY_ADD("connector", m_ms->getConnectorInformation().c_str());
|
||||
LOGFY_ADD("connector", m_ms->getConnectorInformation());
|
||||
|
||||
/* producer > engine state */
|
||||
LOGFY_ADD("secrules_engine",
|
||||
@ -1682,7 +1688,7 @@ std::string Transaction::toJSON(int parts) {
|
||||
for (const auto &a : m_rules->m_components) {
|
||||
yajl_gen_string(g,
|
||||
reinterpret_cast<const unsigned char*>
|
||||
(a.c_str()), a.length());
|
||||
(a.data()), a.length());
|
||||
}
|
||||
yajl_gen_array_close(g);
|
||||
|
||||
@ -1696,20 +1702,20 @@ std::string Transaction::toJSON(int parts) {
|
||||
yajl_gen_array_open(g);
|
||||
for (auto a : m_rulesMessages) {
|
||||
yajl_gen_map_open(g);
|
||||
LOGFY_ADD("message", a.m_message.c_str());
|
||||
LOGFY_ADD("message", a.m_message);
|
||||
yajl_gen_string(g,
|
||||
reinterpret_cast<const unsigned char*>("details"),
|
||||
strlen("details"));
|
||||
yajl_gen_map_open(g);
|
||||
LOGFY_ADD("match", a.m_match.c_str());
|
||||
LOGFY_ADD("reference", a.m_reference.c_str());
|
||||
LOGFY_ADD("ruleId", std::to_string(a.m_rule.m_ruleId).c_str());
|
||||
LOGFY_ADD("file", a.m_rule.getFileName().c_str());
|
||||
LOGFY_ADD("lineNumber", std::to_string(a.m_rule.getLineNumber()).c_str());
|
||||
LOGFY_ADD("data", a.m_data.c_str());
|
||||
LOGFY_ADD("severity", std::to_string(a.m_severity).c_str());
|
||||
LOGFY_ADD("ver", a.m_rule.m_ver.c_str());
|
||||
LOGFY_ADD("rev", a.m_rule.m_rev.c_str());
|
||||
LOGFY_ADD("match", a.m_match);
|
||||
LOGFY_ADD("reference", a.m_reference);
|
||||
LOGFY_ADD("ruleId", std::to_string(a.m_rule.m_ruleId));
|
||||
LOGFY_ADD("file", a.m_rule.getFileName());
|
||||
LOGFY_ADD("lineNumber", std::to_string(a.m_rule.getLineNumber()));
|
||||
LOGFY_ADD("data", a.m_data);
|
||||
LOGFY_ADD("severity", std::to_string(a.m_severity));
|
||||
LOGFY_ADD("ver", a.m_rule.m_ver);
|
||||
LOGFY_ADD("rev", a.m_rule.m_rev);
|
||||
|
||||
yajl_gen_string(g,
|
||||
reinterpret_cast<const unsigned char*>("tags"),
|
||||
@ -1717,13 +1723,13 @@ std::string Transaction::toJSON(int parts) {
|
||||
yajl_gen_array_open(g);
|
||||
for (auto b : a.m_tags) {
|
||||
yajl_gen_string(g,
|
||||
reinterpret_cast<const unsigned char*>(b.c_str()),
|
||||
strlen(b.c_str()));
|
||||
reinterpret_cast<const unsigned char*>(b.data()),
|
||||
b.length());
|
||||
}
|
||||
yajl_gen_array_close(g);
|
||||
|
||||
LOGFY_ADD("maturity", std::to_string(a.m_rule.m_maturity).c_str());
|
||||
LOGFY_ADD("accuracy", std::to_string(a.m_rule.m_accuracy).c_str());
|
||||
LOGFY_ADD("maturity", std::to_string(a.m_rule.m_maturity));
|
||||
LOGFY_ADD("accuracy", std::to_string(a.m_rule.m_accuracy));
|
||||
yajl_gen_map_close(g);
|
||||
yajl_gen_map_close(g);
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ std::string UniqueId::ethernetMacAddress() {
|
||||
(unsigned char)LLADDR(sdl)[3],
|
||||
(unsigned char)LLADDR(sdl)[4],
|
||||
(unsigned char)LLADDR(sdl)[5]);
|
||||
goto end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,7 +177,7 @@ std::string UniqueId::ethernetMacAddress() {
|
||||
(unsigned char)ifr->ifr_addr.sa_data[4],
|
||||
(unsigned char)ifr->ifr_addr.sa_data[5]);
|
||||
|
||||
goto end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(sock);
|
||||
@ -219,7 +219,7 @@ std::string UniqueId::ethernetMacAddress() {
|
||||
(unsigned char)pAdapter->Address[3],
|
||||
(unsigned char)pAdapter->Address[4],
|
||||
(unsigned char)pAdapter->Address[5]);
|
||||
goto end;
|
||||
break;
|
||||
}
|
||||
pAdapter = pAdapter->Next;
|
||||
}
|
||||
@ -227,9 +227,6 @@ std::string UniqueId::ethernetMacAddress() {
|
||||
free(pAdapterInfo);
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__gnu_linux__) || defined(DARWIN) || defined(WIN32)
|
||||
end:
|
||||
#endif
|
||||
return std::string(reinterpret_cast<const char *>(mac));
|
||||
#if defined(__linux__) || defined(__gnu_linux__) || defined(DARWIN) || defined(WIN32)
|
||||
failed:
|
||||
|
@ -226,7 +226,7 @@ static void acmp_build_binary_tree(ACMP *parser, acmp_node_t *node) {
|
||||
|
||||
/* We have array with all children of the node and number of those children
|
||||
*/
|
||||
for (i = 0; i < count - 1; i++)
|
||||
for (i = 0; i < count - 1; i++) {
|
||||
for (j = i + 1; j < count; j++) {
|
||||
acmp_node_t *tmp;
|
||||
|
||||
@ -236,10 +236,11 @@ static void acmp_build_binary_tree(ACMP *parser, acmp_node_t *node) {
|
||||
nodes[i] = nodes[j];
|
||||
nodes[j] = tmp;
|
||||
}
|
||||
if (node->btree != NULL) {
|
||||
free(node->btree);
|
||||
node->btree = NULL;
|
||||
}
|
||||
}
|
||||
if (node->btree != NULL) {
|
||||
free(node->btree);
|
||||
node->btree = NULL;
|
||||
}
|
||||
node->btree = reinterpret_cast<acmp_btree_node_t *>(calloc(1, sizeof(acmp_btree_node_t)));
|
||||
|
||||
/* ENH: Check alloc succeded */
|
||||
|
@ -110,15 +110,18 @@ bool HttpsClient::download(const std::string &uri) {
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "ModSecurity3");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers_chunk);
|
||||
|
||||
/* We want Curl to return error in case there is an HTTP error code */
|
||||
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
|
||||
|
||||
if (m_requestBody.empty() == false) {
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, m_requestBody.c_str());
|
||||
headers_chunk = curl_slist_append(headers_chunk, "Expect:"); // Disable Expect: 100-continue
|
||||
}
|
||||
|
||||
/* set HTTP headers for request */
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers_chunk);
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
curl_slist_free_all(headers_chunk);
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#include "src/utils/geo_lookup.h"
|
||||
|
||||
#ifndef WITH_PCRE2
|
||||
#ifdef WITH_PCRE
|
||||
#if PCRE_HAVE_JIT
|
||||
// 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.
|
||||
@ -35,11 +35,11 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
class Pcre2MatchContextPtr {
|
||||
public:
|
||||
Pcre2MatchContextPtr()
|
||||
: m_match_context(pcre2_match_context_create(NULL)) {}
|
||||
: m_match_context(pcre2_match_context_create(nullptr)) {}
|
||||
|
||||
Pcre2MatchContextPtr(const Pcre2MatchContextPtr&) = delete;
|
||||
Pcre2MatchContextPtr& operator=(const Pcre2MatchContextPtr&) = delete;
|
||||
@ -48,7 +48,7 @@ class Pcre2MatchContextPtr {
|
||||
pcre2_match_context_free(m_match_context);
|
||||
}
|
||||
|
||||
operator pcre2_match_context*() const {
|
||||
explicit operator pcre2_match_context*() const {
|
||||
return m_match_context;
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ namespace Utils {
|
||||
|
||||
// Helper function to tell us if the current config indicates CRLF is a valid newline sequence
|
||||
bool crlfIsNewline() {
|
||||
#if WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
uint32_t newline = 0;
|
||||
pcre2_config(PCRE2_CONFIG_NEWLINE, &newline);
|
||||
bool crlf_is_newline =
|
||||
@ -89,7 +89,7 @@ bool crlfIsNewline() {
|
||||
|
||||
Regex::Regex(const std::string& pattern_, bool ignoreCase)
|
||||
: pattern(pattern_.empty() ? ".*" : pattern_) {
|
||||
#if WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
PCRE2_SPTR pcre2_pattern = reinterpret_cast<PCRE2_SPTR>(pattern.c_str());
|
||||
uint32_t pcre2_options = (PCRE2_DOTALL|PCRE2_MULTILINE);
|
||||
if (ignoreCase) {
|
||||
@ -98,10 +98,10 @@ Regex::Regex(const std::string& pattern_, bool ignoreCase)
|
||||
int errornumber = 0;
|
||||
PCRE2_SIZE erroroffset = 0;
|
||||
m_pc = pcre2_compile(pcre2_pattern, PCRE2_ZERO_TERMINATED,
|
||||
pcre2_options, &errornumber, &erroroffset, NULL);
|
||||
pcre2_options, &errornumber, &erroroffset, nullptr);
|
||||
m_pcje = pcre2_jit_compile(m_pc, PCRE2_JIT_COMPLETE);
|
||||
#else
|
||||
const char *errptr = NULL;
|
||||
const char *errptr = nullptr;
|
||||
int erroffset;
|
||||
int flags = (PCRE_DOTALL|PCRE_MULTILINE);
|
||||
|
||||
@ -109,7 +109,7 @@ Regex::Regex(const std::string& pattern_, bool ignoreCase)
|
||||
flags |= PCRE_CASELESS;
|
||||
}
|
||||
m_pc = pcre_compile(pattern.c_str(), flags,
|
||||
&errptr, &erroffset, NULL);
|
||||
&errptr, &erroffset, nullptr);
|
||||
|
||||
m_pce = pcre_study(m_pc, pcre_study_opt, &errptr);
|
||||
#endif
|
||||
@ -117,20 +117,20 @@ Regex::Regex(const std::string& pattern_, bool ignoreCase)
|
||||
|
||||
|
||||
Regex::~Regex() {
|
||||
#if WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
pcre2_code_free(m_pc);
|
||||
#else
|
||||
if (m_pc != NULL) {
|
||||
if (m_pc != nullptr) {
|
||||
pcre_free(m_pc);
|
||||
m_pc = NULL;
|
||||
m_pc = nullptr;
|
||||
}
|
||||
if (m_pce != NULL) {
|
||||
if (m_pce != nullptr) {
|
||||
#if PCRE_HAVE_JIT
|
||||
pcre_free_study(m_pce);
|
||||
#else
|
||||
pcre_free(m_pce);
|
||||
#endif
|
||||
m_pce = NULL;
|
||||
m_pce = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -139,20 +139,20 @@ Regex::~Regex() {
|
||||
std::list<SMatch> Regex::searchAll(const std::string& s) const {
|
||||
std::list<SMatch> retList;
|
||||
int rc = 0;
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
PCRE2_SPTR pcre2_s = reinterpret_cast<PCRE2_SPTR>(s.c_str());
|
||||
PCRE2_SIZE offset = 0;
|
||||
|
||||
pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_pc, NULL);
|
||||
pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_pc, nullptr);
|
||||
do {
|
||||
if (m_pcje == 0) {
|
||||
rc = pcre2_jit_match(m_pc, pcre2_s, s.length(),
|
||||
offset, 0, match_data, NULL);
|
||||
offset, 0, match_data, nullptr);
|
||||
}
|
||||
|
||||
if (m_pcje != 0 || rc == PCRE2_ERROR_JIT_STACKLIMIT) {
|
||||
rc = pcre2_match(m_pc, pcre2_s, s.length(),
|
||||
offset, PCRE2_NO_JIT, match_data, NULL);
|
||||
offset, PCRE2_NO_JIT, match_data, nullptr);
|
||||
}
|
||||
const PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
|
||||
#else
|
||||
@ -183,29 +183,29 @@ std::list<SMatch> Regex::searchAll(const std::string& s) const {
|
||||
}
|
||||
} while (rc > 0);
|
||||
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
pcre2_match_data_free(match_data);
|
||||
#endif
|
||||
return retList;
|
||||
}
|
||||
|
||||
RegexResult Regex::searchOneMatch(const std::string& s, std::vector<SMatchCapture>& captures, unsigned long match_limit) const {
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
Pcre2MatchContextPtr match_context;
|
||||
if (match_limit > 0) {
|
||||
// TODO: What if setting the match limit fails?
|
||||
pcre2_set_match_limit(match_context, match_limit);
|
||||
pcre2_set_match_limit(static_cast<pcre2_match_context*>(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);
|
||||
pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_pc, nullptr);
|
||||
int rc = 0;
|
||||
if (m_pcje == 0) {
|
||||
rc = pcre2_jit_match(m_pc, pcre2_s, s.length(), 0, 0, match_data, match_context);
|
||||
rc = pcre2_jit_match(m_pc, pcre2_s, s.length(), 0, 0, match_data, static_cast<pcre2_match_context*>(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, match_context);
|
||||
rc = pcre2_match(m_pc, pcre2_s, s.length(), 0, PCRE2_NO_JIT, match_data, static_cast<pcre2_match_context*>(match_context));
|
||||
}
|
||||
const PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
|
||||
#else
|
||||
@ -214,7 +214,7 @@ RegexResult Regex::searchOneMatch(const std::string& s, std::vector<SMatchCaptur
|
||||
pcre_extra local_pce;
|
||||
pcre_extra *pce = m_pce;
|
||||
|
||||
if (m_pce != NULL && match_limit > 0) {
|
||||
if (m_pce != nullptr && match_limit > 0) {
|
||||
local_pce = *m_pce;
|
||||
local_pce.match_limit = match_limit;
|
||||
local_pce.flags |= PCRE_EXTRA_MATCH_LIMIT;
|
||||
@ -235,7 +235,7 @@ RegexResult Regex::searchOneMatch(const std::string& s, std::vector<SMatchCaptur
|
||||
captures.push_back(capture);
|
||||
}
|
||||
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
pcre2_match_data_free(match_data);
|
||||
#endif
|
||||
return to_regex_result(rc);
|
||||
@ -243,24 +243,24 @@ RegexResult Regex::searchOneMatch(const std::string& s, std::vector<SMatchCaptur
|
||||
|
||||
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
|
||||
#ifndef WITH_PCRE
|
||||
Pcre2MatchContextPtr match_context;
|
||||
if (match_limit > 0) {
|
||||
// TODO: What if setting the match limit fails?
|
||||
pcre2_set_match_limit(match_context, match_limit);
|
||||
pcre2_set_match_limit(static_cast<pcre2_match_context*>(match_context), match_limit);
|
||||
}
|
||||
|
||||
PCRE2_SPTR pcre2_s = reinterpret_cast<PCRE2_SPTR>(s.c_str());
|
||||
PCRE2_SIZE startOffset = 0;
|
||||
|
||||
pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_pc, NULL);
|
||||
pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_pc, nullptr);
|
||||
while (startOffset <= s.length()) {
|
||||
uint32_t pcre2_options = 0;
|
||||
if (prev_match_zero_length) {
|
||||
pcre2_options = PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED;
|
||||
}
|
||||
int rc = pcre2_match(m_pc, pcre2_s, s.length(),
|
||||
startOffset, pcre2_options, match_data, match_context);
|
||||
startOffset, pcre2_options, match_data, static_cast<pcre2_match_context*>(match_context));
|
||||
const PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
|
||||
|
||||
#else
|
||||
@ -268,7 +268,7 @@ RegexResult Regex::searchGlobal(const std::string& s, std::vector<SMatchCapture>
|
||||
pcre_extra local_pce;
|
||||
pcre_extra *pce = m_pce;
|
||||
|
||||
if (m_pce != NULL && match_limit > 0) {
|
||||
if (m_pce != nullptr && match_limit > 0) {
|
||||
local_pce = *m_pce;
|
||||
local_pce.match_limit = match_limit;
|
||||
local_pce.flags |= PCRE_EXTRA_MATCH_LIMIT;
|
||||
@ -337,25 +337,25 @@ RegexResult Regex::searchGlobal(const std::string& s, std::vector<SMatchCapture>
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
pcre2_match_data_free(match_data);
|
||||
#endif
|
||||
return RegexResult::Ok;
|
||||
}
|
||||
|
||||
int Regex::search(const std::string& s, SMatch *match) const {
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
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);
|
||||
pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_pc, nullptr);
|
||||
int ret = 0;
|
||||
if (m_pcje == 0) {
|
||||
ret = pcre2_match(m_pc, pcre2_s, s.length(),
|
||||
0, 0, match_data, NULL) > 0;
|
||||
0, 0, match_data, nullptr) > 0;
|
||||
}
|
||||
|
||||
if (m_pcje != 0 || ret == PCRE2_ERROR_JIT_STACKLIMIT) {
|
||||
ret = pcre2_match(m_pc, pcre2_s, s.length(),
|
||||
0, PCRE2_NO_JIT, match_data, NULL) > 0;
|
||||
0, PCRE2_NO_JIT, match_data, nullptr) > 0;
|
||||
}
|
||||
if (ret > 0) { // match
|
||||
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
|
||||
@ -371,23 +371,23 @@ int Regex::search(const std::string& s, SMatch *match) const {
|
||||
0);
|
||||
}
|
||||
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
pcre2_match_data_free(match_data);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Regex::search(const std::string& s) const {
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
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);
|
||||
pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_pc, nullptr);
|
||||
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, nullptr);
|
||||
}
|
||||
|
||||
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, nullptr);
|
||||
}
|
||||
pcre2_match_data_free(match_data);
|
||||
if (rc > 0) {
|
||||
@ -405,7 +405,7 @@ int Regex::search(const std::string& s) const {
|
||||
RegexResult Regex::to_regex_result(int pcre_exec_result) const {
|
||||
if (
|
||||
pcre_exec_result > 0 ||
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
pcre_exec_result == PCRE2_ERROR_NOMATCH
|
||||
#else
|
||||
pcre_exec_result == PCRE_ERROR_NOMATCH
|
||||
@ -413,7 +413,7 @@ RegexResult Regex::to_regex_result(int pcre_exec_result) const {
|
||||
) {
|
||||
return RegexResult::Ok;
|
||||
} else if(
|
||||
#ifdef WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
pcre_exec_result == PCRE2_ERROR_MATCHLIMIT
|
||||
#else
|
||||
pcre_exec_result == PCRE_ERROR_MATCHLIMIT
|
||||
|
@ -12,7 +12,7 @@
|
||||
* directly using the email address security@modsecurity.org.
|
||||
*
|
||||
*/
|
||||
#if WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
#define PCRE2_CODE_UNIT_WIDTH 8
|
||||
#include <pcre2.h>
|
||||
#else
|
||||
@ -79,7 +79,7 @@ class Regex {
|
||||
Regex& operator=(const Regex&) = delete;
|
||||
|
||||
bool hasError() const {
|
||||
return (m_pc == NULL);
|
||||
return (m_pc == nullptr);
|
||||
}
|
||||
std::list<SMatch> searchAll(const std::string& s) const;
|
||||
RegexResult searchOneMatch(const std::string& s, std::vector<SMatchCapture>& captures, unsigned long match_limit = 0) const;
|
||||
@ -91,12 +91,12 @@ class Regex {
|
||||
private:
|
||||
RegexResult to_regex_result(int pcre_exec_result) const;
|
||||
|
||||
#if WITH_PCRE2
|
||||
#ifndef WITH_PCRE
|
||||
pcre2_code *m_pc;
|
||||
int m_pcje;
|
||||
#else
|
||||
pcre *m_pc = NULL;
|
||||
pcre_extra *m_pce = NULL;
|
||||
pcre *m_pc = nullptr;
|
||||
pcre_extra *m_pce = nullptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -79,7 +79,7 @@ void XML::evaluate(Transaction *t,
|
||||
}
|
||||
|
||||
/* Process the XPath expression. */
|
||||
xpathExpr = (const xmlChar*)param.c_str();
|
||||
xpathExpr = reinterpret_cast<const xmlChar*>(param.c_str());
|
||||
xpathCtx = xmlXPathNewContext(t->m_xml->m_data.doc);
|
||||
if (xpathCtx == NULL) {
|
||||
ms_dbg_a(t, 1, "XML: Unable to create new XPath context. : ");
|
||||
@ -91,9 +91,9 @@ void XML::evaluate(Transaction *t,
|
||||
} else {
|
||||
std::vector<actions::Action *> acts = rule->getActionsByName("xmlns", t);
|
||||
for (auto &x : acts) {
|
||||
actions::XmlNS *z = (actions::XmlNS *)x;
|
||||
if (xmlXPathRegisterNs(xpathCtx, (const xmlChar*)z->m_scope.c_str(),
|
||||
(const xmlChar*)z->m_href.c_str()) != 0) {
|
||||
actions::XmlNS *z = static_cast<actions::XmlNS *>(x);
|
||||
if (xmlXPathRegisterNs(xpathCtx, reinterpret_cast<const xmlChar*>(z->m_scope.c_str()),
|
||||
reinterpret_cast<const xmlChar*>(z->m_href.c_str())) != 0) {
|
||||
ms_dbg_a(t, 1, "Failed to register XML namespace href \"" + \
|
||||
z->m_href + "\" prefix \"" + z->m_scope + "\".");
|
||||
return;
|
||||
|
@ -72,7 +72,7 @@ unit_tests_LDFLAGS = \
|
||||
|
||||
unit_tests_CPPFLAGS = \
|
||||
-Icommon \
|
||||
-I../ \
|
||||
-I$(top_srcdir)/ \
|
||||
-g \
|
||||
-I$(top_builddir)/headers \
|
||||
$(CURL_CFLAGS) \
|
||||
@ -127,7 +127,7 @@ regression_tests_LDFLAGS = \
|
||||
|
||||
regression_tests_CPPFLAGS = \
|
||||
-Icommon \
|
||||
-I../ \
|
||||
-I$(top_srcdir) \
|
||||
-g \
|
||||
-I$(top_builddir)/headers \
|
||||
$(CURL_CFLAGS) \
|
||||
@ -179,7 +179,7 @@ rules_optimization_LDFLAGS = \
|
||||
|
||||
rules_optimization_CPPFLAGS = \
|
||||
-Icommon \
|
||||
-I../ \
|
||||
-I$(top_srcdir)/ \
|
||||
-g \
|
||||
-I$(top_builddir)/headers \
|
||||
$(CURL_CFLAGS) \
|
||||
|
@ -10,6 +10,7 @@ benchmark_LDADD = \
|
||||
$(GEOIP_LDADD) \
|
||||
$(MAXMIND_LDADD) \
|
||||
$(PCRE_LDADD) \
|
||||
$(PCRE2_LDADD) \
|
||||
$(YAJL_LDADD) \
|
||||
$(LMDB_LDADD) \
|
||||
$(SSDEEP_LDADD) \
|
||||
@ -35,6 +36,7 @@ benchmark_CPPFLAGS = \
|
||||
-I$(top_builddir)/headers \
|
||||
$(GLOBAL_CPPFLAGS) \
|
||||
$(PCRE_CFLAGS) \
|
||||
$(PCRE2_CFLAGS) \
|
||||
$(LMDB_CFLAGS) \
|
||||
$(LIBXML2_CFLAGS)
|
||||
|
||||
|
@ -31,6 +31,8 @@ accessMoved:seclang-parser.hh
|
||||
returnTempReference:seclang-parser.hh
|
||||
duplInheritedMember:seclang-parser.hh
|
||||
constVariableReference:seclang-parser.hh
|
||||
uninitMemberVar:seclang-parser.hh
|
||||
|
||||
|
||||
unreadVariable:src/operators/rx.cc
|
||||
unreadVariable:src/operators/rx_global.cc
|
||||
@ -59,3 +61,4 @@ uselessCallsSubstr
|
||||
|
||||
// Examples
|
||||
memleak:examples/using_bodies_in_chunks/simple_request.cc
|
||||
|
||||
|
@ -18,6 +18,7 @@ afl_fuzzer_LDADD = \
|
||||
$(CURL_LDADD) \
|
||||
$(GEOIP_LDFLAGS) $(GEOIP_LDADD) \
|
||||
$(PCRE_LDADD) \
|
||||
$(PCRE2_LDADD) \
|
||||
$(YAJL_LDFLAGS) $(YAJL_LDADD) \
|
||||
$(LMDB_LDFLAGS) $(LMDB_LDADD) \
|
||||
$(MAXMIND_LDFLAGS) $(MAXMIND_LDADD) \
|
||||
@ -44,4 +45,5 @@ afl_fuzzer_CPPFLAGS = \
|
||||
$(YAJL_CFLAGS) \
|
||||
$(LMDB_CFLAGS) \
|
||||
$(PCRE_CFLAGS) \
|
||||
$(PCRE2_CFLAGS) \
|
||||
$(LIBXML2_CFLAGS)
|
||||
|
2
test/test-cases/data/pattern-file1.data
Normal file
2
test/test-cases/data/pattern-file1.data
Normal file
@ -0,0 +1,2 @@
|
||||
# comment
|
||||
pattern1
|
2
test/test-cases/data/pattern-file2.data
Normal file
2
test/test-cases/data/pattern-file2.data
Normal file
@ -0,0 +1,2 @@
|
||||
# comment
|
||||
pattern2
|
@ -144,7 +144,7 @@
|
||||
"resource":"libxml2",
|
||||
"title":"Testing CtlRequestBodyProcessor=XML (3)",
|
||||
"expected":{
|
||||
"debug_log": "XML: Failed parsing document."
|
||||
"debug_log": "XML: Failed to parse document."
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
|
@ -172,6 +172,65 @@
|
||||
"SecAuditLogRelevantStatus \"^(?:5|4(?!04))\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
"version_max": 0,
|
||||
"title": "auditlog : basic parser test - JSON",
|
||||
"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": ""
|
||||
},
|
||||
"response": {
|
||||
"headers": {
|
||||
"Content-Type": "plain\/text\n\r"
|
||||
},
|
||||
"body": [
|
||||
"test"
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "{\"transaction\":{\"client_ip\":\"200.249.12.31\",\"time_stamp\":\"\\S{3} \\S{3} [ \\d]\\d \\d{2}:\\d{2}:\\d{2} \\d{4}\"",
|
||||
"debug_log": "",
|
||||
"error_log": "",
|
||||
"http_code": 403
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@contains test\" \"id:1,t:trim,deny,auditlog\"",
|
||||
"SecAuditEngine RelevantOnly",
|
||||
"SecAuditLogFormat JSON",
|
||||
"SecAuditLogParts ABCFHZ",
|
||||
"SecAuditLogStorageDir /tmp/test",
|
||||
"SecAuditLog /tmp/audit_test_parallel.log",
|
||||
"SecAuditLogDirMode 0766",
|
||||
"SecAuditLogFileMode 0600",
|
||||
"SecAuditLogType Serial",
|
||||
"SecAuditLogRelevantStatus \"^(?:5|4(?!04))\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
@ -418,5 +477,64 @@
|
||||
"SecAuditLogType Serial",
|
||||
"SecAuditLogRelevantStatus \"^(?:5|4(?!04))\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
"version_max": 0,
|
||||
"title": "auditlog : SecAuditLogPrefix",
|
||||
"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": ""
|
||||
},
|
||||
"response": {
|
||||
"headers": {
|
||||
"Content-Type": "plain\/text\n\r"
|
||||
},
|
||||
"body": [
|
||||
"test"
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"audit_log": "\\[audit\\.log]:\\ ---.*\\[audit\\.log]:\\ Keep-Alive",
|
||||
"debug_log": "",
|
||||
"error_log": "",
|
||||
"http_code": 403
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@contains test\" \"id:1,t:trim,deny,auditlog\"",
|
||||
"SecAuditEngine RelevantOnly",
|
||||
"SecAuditLogPrefix \"[audit.log]: \"",
|
||||
"SecAuditLogParts ABCFHZ",
|
||||
"SecAuditLogStorageDir /tmp/test",
|
||||
"SecAuditLog /tmp/audit_test_prefix.log",
|
||||
"SecAuditLogDirMode 0766",
|
||||
"SecAuditLogFileMode 0600",
|
||||
"SecAuditLogType Serial",
|
||||
"SecAuditLogRelevantStatus \"^(?:5|4(?!04))\""
|
||||
]
|
||||
}
|
||||
]
|
||||
|
39
test/test-cases/regression/operator-pmfromfile.json
Normal file
39
test/test-cases/regression/operator-pmfromfile.json
Normal file
@ -0,0 +1,39 @@
|
||||
[
|
||||
{
|
||||
"enabled": 1,
|
||||
"version_min": 300000,
|
||||
"version_max": 0,
|
||||
"title": "pmFromFile operator test",
|
||||
"client": {
|
||||
"ip": "10.20.30.40",
|
||||
"port": 2313
|
||||
},
|
||||
"server": {
|
||||
"ip": "1.2.3.4",
|
||||
"port": 80
|
||||
},
|
||||
"request": {
|
||||
"headers": {
|
||||
"Host": "foobar.com"
|
||||
},
|
||||
"uri": "\/test.php?param1=pattern2",
|
||||
"method": "GET",
|
||||
"http_version": 1.1,
|
||||
"body": ""
|
||||
},
|
||||
"response": {
|
||||
"headers": {
|
||||
"Content-Type": "text\/html; charset=utf-8\n\r",
|
||||
"Content-Length": "10\n\r"
|
||||
}
|
||||
},
|
||||
"expected": {
|
||||
"debug_log": "Rule returned 1",
|
||||
"http_code": 403
|
||||
},
|
||||
"rules": [
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@pmFromFile test-cases/data/pattern-file1.data test-cases/data/pattern-file2.data\" \"phase:1,id:999,deny\""
|
||||
]
|
||||
}
|
||||
]
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VAR (1/2)",
|
||||
"title":"Testing Variables :: MATCHED_VAR (1/5)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
@ -42,7 +42,7 @@
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VAR (2/2)",
|
||||
"title":"Testing Variables :: MATCHED_VAR (2/5)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
@ -81,6 +81,128 @@
|
||||
"SecRule MATCHED_VAR \"@contains other_value\" \"id:29,pass\"",
|
||||
"SecRule MATCHED_VAR \"@contains other_value\" \"id:30,pass\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VAR (3/5)",
|
||||
"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":"/?foo=1&bar=2&baz=2",
|
||||
"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":{
|
||||
"http_code": 200
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@rx 1\" \"id:1,phase:1,pass\"",
|
||||
"SecRule ARGS \"@rx 2\" \"id:2,phase:1,pass\"",
|
||||
"SecRule MATCHED_VAR \"@eq 1\" \"id:3,phase:1,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VAR (4/5)",
|
||||
"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":"/?foo=1&bar=2&baz=2",
|
||||
"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":{
|
||||
"http_code": 200
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@rx 1\" \"id:1,phase:1,pass\"",
|
||||
"SecRule ARGS \"@rx 2\" \"id:2,phase:1,pass\"",
|
||||
"SecRule MATCHED_VAR \"@eq 2\" \"id:3,phase:1,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VAR (5/5)",
|
||||
"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":"/?foo=1&bar=2&baz=2",
|
||||
"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":{
|
||||
"http_code": 403
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@rx 1\" \"id:1,phase:1,pass\"",
|
||||
"SecRule ARGS \"@rx 2\" \"id:2,phase:1,deny,status:403,chain\"",
|
||||
"SecRule MATCHED_VAR \"@eq 2\""
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VARS (1/2)",
|
||||
"title":"Testing Variables :: MATCHED_VARS (1/6)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
@ -43,7 +43,7 @@
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VARS (2/2)",
|
||||
"title":"Testing Variables :: MATCHED_VARS (2/6)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
@ -81,6 +81,169 @@
|
||||
"SecRule MATCHED_VARS \"@contains asdf\" \"\"",
|
||||
"SecRule MATCHED_VARS \"@contains value\" \"id:29\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VARS (3/6)",
|
||||
"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":"/?foo=1&bar=2&baz=2",
|
||||
"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":{
|
||||
"http_code": 200
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@rx 1\" \"id:1,phase:1,pass\"",
|
||||
"SecRule ARGS \"@rx 2\" \"id:2,phase:1,pass\"",
|
||||
"SecRule MATCHED_VARS \"@contains 1\" \"id:3,phase:1,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VARS (4/6)",
|
||||
"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":"/?foo=1&bar=2&baz=2",
|
||||
"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":{
|
||||
"http_code": 200
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@rx 1\" \"id:1,phase:1,pass\"",
|
||||
"SecRule ARGS \"@rx 2\" \"id:2,phase:1,pass\"",
|
||||
"SecRule MATCHED_VARS \"@contains 2\" \"id:3,phase:1,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VARS (5/6)",
|
||||
"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":"/?foo=1&bar=2&baz=2",
|
||||
"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":{
|
||||
"http_code": 200
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@rx 1\" \"id:1,phase:1,pass\"",
|
||||
"SecRule ARGS \"@rx 2\" \"id:2,phase:1,pass\"",
|
||||
"SecRule MATCHED_VARS \"@within 1 2\" \"id:3,phase:1,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VARS (6/6)",
|
||||
"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":"/?foo=1&bar=2&baz=2",
|
||||
"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":{
|
||||
"http_code": 403
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@rx 1\" \"id:1,phase:1,pass\"",
|
||||
"SecRule ARGS \"@rx 2\" \"id:2,phase:1,deny,status:403,chain\"",
|
||||
"SecRule MATCHED_VARS \"@eq 2\""
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VARS_NAMES (1/2)",
|
||||
"title":"Testing Variables :: MATCHED_VARS_NAMES (1/5)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
@ -43,7 +43,7 @@
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VARS_NAMES (2/2)",
|
||||
"title":"Testing Variables :: MATCHED_VARS_NAMES (2/5)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
@ -81,6 +81,128 @@
|
||||
"SecRule MATCHED_VARS_NAMES \"@contains asdf\" \"\"",
|
||||
"SecRule MATCHED_VARS_NAMES \"@contains value\" \"id:29\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VARS_NAMES (3/5)",
|
||||
"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":"/?foo=1&bar=2&baz=2",
|
||||
"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":{
|
||||
"http_code": 200
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@rx 1\" \"id:1,phase:1,pass\"",
|
||||
"SecRule ARGS \"@rx 2\" \"id:2,phase:1,pass\"",
|
||||
"SecRule MATCHED_VARS_NAMES \"@within ARGS:foo ARGS:bar ARGS:baz\" \"id:3,phase:1,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VARS_NAMES (4/5)",
|
||||
"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":"/?foo=1&bar=2&baz=2",
|
||||
"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":{
|
||||
"http_code": 200
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@rx 1\" \"id:1,phase:1,pass\"",
|
||||
"SecRule ARGS \"@rx 2\" \"id:2,phase:1,deny,status:403,chain\"",
|
||||
"SecRule MATCHED_VARS_NAMES \"@strEq ARGS:foo\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VARS_NAMES (5/5)",
|
||||
"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":"/?foo=1&bar=2&baz=2",
|
||||
"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":{
|
||||
"http_code": 403
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@rx 1\" \"id:1,phase:1,pass\"",
|
||||
"SecRule ARGS \"@rx 2\" \"id:2,phase:1,deny,status:403,chain\"",
|
||||
"SecRule MATCHED_VARS_NAMES \"@within ARGS:bar ARGS:baz\""
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VAR_NAME (1/3)",
|
||||
"title":"Testing Variables :: MATCHED_VAR_NAME (1/7)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
@ -43,7 +43,7 @@
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VAR_NAME (2/3)",
|
||||
"title":"Testing Variables :: MATCHED_VAR_NAME (2/7)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
@ -85,7 +85,7 @@
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VAR_NAME (3/3)",
|
||||
"title":"Testing Variables :: MATCHED_VAR_NAME (3/7)",
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
@ -121,6 +121,169 @@
|
||||
"SecRule ARGS_NAMES \"@contains ey1\" \"chain,id:30,pass\"",
|
||||
"SecRule MATCHED_VAR_NAME \"@contains key1\" \"id:31\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VAR_NAME (4/7)",
|
||||
"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":"/?foo=1&bar=2&baz=2",
|
||||
"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":{
|
||||
"http_code": 200
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@rx 1\" \"id:1,phase:1,pass\"",
|
||||
"SecRule ARGS \"@rx 2\" \"id:2,phase:1,pass\"",
|
||||
"SecRule MATCHED_VAR_NAME \"@strEq ARGS:foo\" \"id:3,phase:1,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VAR_NAME (5/7)",
|
||||
"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":"/?foo=1&bar=2&baz=2",
|
||||
"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":{
|
||||
"http_code": 200
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@rx 1\" \"id:1,phase:1,pass\"",
|
||||
"SecRule ARGS \"@rx 2\" \"id:2,phase:1,pass\"",
|
||||
"SecRule MATCHED_VAR_NAME \"@strEq ARGS:bar\" \"id:3,phase:1,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VAR_NAME (6/7)",
|
||||
"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":"/?foo=1&bar=2&baz=2",
|
||||
"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":{
|
||||
"http_code": 200
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@rx 1\" \"id:1,phase:1,pass\"",
|
||||
"SecRule ARGS \"@rx 2\" \"id:2,phase:1,pass\"",
|
||||
"SecRule MATCHED_VAR_NAME \"@strEq ARGS:baz\" \"id:3,phase:1,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"title":"Testing Variables :: MATCHED_VAR_NAME (7/7)",
|
||||
"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":"/?foo=1&bar=2&baz=2",
|
||||
"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":{
|
||||
"http_code": 403
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRule ARGS \"@rx 1\" \"id:1,phase:1,pass\"",
|
||||
"SecRule ARGS \"@rx 2\" \"id:2,phase:1,deny,status:403,chain\"",
|
||||
"SecRule MATCHED_VAR_NAME \"@within ARGS:baz ARGS:bar\""
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -70,7 +70,7 @@
|
||||
]
|
||||
},
|
||||
"expected":{
|
||||
"debug_log":"XML parsing error: XML: Failed parsing document"
|
||||
"debug_log":"XML parsing error: XML: Failed to parse document"
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
|
@ -30,7 +30,6 @@
|
||||
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||
"</bookstore>"
|
||||
]
|
||||
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
@ -42,6 +41,580 @@
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||
"SecRule XML://bookstore/*[local-name()='some-tag'] \"bbb\" \"id:500012,phase:3,t:none,t:lowercase,log,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"resource":"libxml2",
|
||||
"title":"Testing XML parsing to ARGS with On, check if ARGS is populated",
|
||||
"expected":{
|
||||
"http_code": 403
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"Content-Type": "text/xml"
|
||||
},
|
||||
"uri":"/",
|
||||
"method":"POST",
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
||||
"<!DOCTYPE author [",
|
||||
"<!ELEMENT book ANY>",
|
||||
"<!ENTITY js SYSTEM \"/etc/passwd\">",
|
||||
"]>",
|
||||
"<bookstore>",
|
||||
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||
"</bookstore>"
|
||||
]
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRequestBodyAccess On",
|
||||
"SecParseXmlIntoArgs On",
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||
"SecRule ARGS:xml.bookstore.some-tag \"@rx aaa\" \"id:500012,phase:2,t:none,t:lowercase,log,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"resource":"libxml2",
|
||||
"title":"Testing XML parsing to ARGS with On, check if XML is populated",
|
||||
"expected":{
|
||||
"http_code": 403
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"Content-Type": "text/xml"
|
||||
},
|
||||
"uri":"/",
|
||||
"method":"POST",
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
||||
"<!DOCTYPE author [",
|
||||
"<!ELEMENT book ANY>",
|
||||
"<!ENTITY js SYSTEM \"/etc/passwd\">",
|
||||
"]>",
|
||||
"<bookstore>",
|
||||
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||
"</bookstore>"
|
||||
]
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRequestBodyAccess On",
|
||||
"SecParseXmlIntoArgs On",
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||
"SecRule XML:/* \"@rx aaa\" \"id:500012,phase:2,t:none,t:lowercase,log,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"resource":"libxml2",
|
||||
"title":"Testing XML parsing to ARGS with OnlyArgs, check if ARGS is populated",
|
||||
"expected":{
|
||||
"http_code": 403
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"Content-Type": "text/xml"
|
||||
},
|
||||
"uri":"/",
|
||||
"method":"POST",
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
||||
"<!DOCTYPE author [",
|
||||
"<!ELEMENT book ANY>",
|
||||
"<!ENTITY js SYSTEM \"/etc/passwd\">",
|
||||
"]>",
|
||||
"<bookstore>",
|
||||
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||
"</bookstore>"
|
||||
]
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRequestBodyAccess On",
|
||||
"SecParseXmlIntoArgs OnlyArgs",
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||
"SecRule ARGS:xml.bookstore.some-tag \"@rx aaa\" \"id:500012,phase:2,t:none,t:lowercase,log,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"resource":"libxml2",
|
||||
"title":"Testing XML parsing to ARGS with OnlyArgs, check if XML is populated",
|
||||
"expected":{
|
||||
"http_code": 200
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"Content-Type": "text/xml"
|
||||
},
|
||||
"uri":"/",
|
||||
"method":"POST",
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
||||
"<!DOCTYPE author [",
|
||||
"<!ELEMENT book ANY>",
|
||||
"<!ENTITY js SYSTEM \"/etc/passwd\">",
|
||||
"]>",
|
||||
"<bookstore>",
|
||||
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||
"</bookstore>"
|
||||
]
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRequestBodyAccess On",
|
||||
"SecParseXmlIntoArgs OnlyArgs",
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||
"SecRule XML:/* \"@rx aaa\" \"id:500012,phase:2,t:none,t:lowercase,log,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"resource":"libxml2",
|
||||
"title":"Testing XML parsing to ARGS with Off, check if ARGS is populated",
|
||||
"expected":{
|
||||
"http_code": 200
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"Content-Type": "text/xml"
|
||||
},
|
||||
"uri":"/",
|
||||
"method":"POST",
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
||||
"<!DOCTYPE author [",
|
||||
"<!ELEMENT book ANY>",
|
||||
"<!ENTITY js SYSTEM \"/etc/passwd\">",
|
||||
"]>",
|
||||
"<bookstore>",
|
||||
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||
"</bookstore>"
|
||||
]
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRequestBodyAccess On",
|
||||
"SecParseXmlIntoArgs Off",
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||
"SecRule ARGS \"@rx aaa\" \"id:500012,phase:2,t:none,t:lowercase,log,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"resource":"libxml2",
|
||||
"title":"Testing XML parsing to ARGS with Off, check if XML is populated",
|
||||
"expected":{
|
||||
"http_code": 403
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"Content-Type": "text/xml"
|
||||
},
|
||||
"uri":"/",
|
||||
"method":"POST",
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
||||
"<!DOCTYPE author [",
|
||||
"<!ELEMENT book ANY>",
|
||||
"<!ENTITY js SYSTEM \"/etc/passwd\">",
|
||||
"]>",
|
||||
"<bookstore>",
|
||||
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||
"</bookstore>"
|
||||
]
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRequestBodyAccess On",
|
||||
"SecParseXmlIntoArgs Off",
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||
"SecRule XML:/* \"@rx aaa\" \"id:500012,phase:2,t:none,t:lowercase,log,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"resource":"libxml2",
|
||||
"title":"Testing XML parsing to ARGS with On, turn Off with ctl, check ARGS",
|
||||
"expected":{
|
||||
"http_code": 200
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"Content-Type": "text/xml"
|
||||
},
|
||||
"uri":"/?q=xml",
|
||||
"method":"POST",
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
||||
"<!DOCTYPE author [",
|
||||
"<!ELEMENT book ANY>",
|
||||
"<!ENTITY js SYSTEM \"/etc/passwd\">",
|
||||
"]>",
|
||||
"<bookstore>",
|
||||
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||
"</bookstore>"
|
||||
]
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRequestBodyAccess On",
|
||||
"SecParseXmlIntoArgs On",
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||
"SecRule ARGS_GET:q \"@rx xml\" \"id:500012,phase:1,t:none,t:lowercase,ctl:parseXmlIntoArgs=Off\"",
|
||||
"SecRule ARGS:xml.bookstore.some-tag \"@rx aaa\" \"id:500013,phase:2,t:none,t:lowercase,log,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"resource":"libxml2",
|
||||
"title":"Testing XML parsing to ARGS with On, turn Off with ctl, check XML",
|
||||
"expected":{
|
||||
"http_code": 403
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"Content-Type": "text/xml"
|
||||
},
|
||||
"uri":"/?q=xml",
|
||||
"method":"POST",
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
||||
"<!DOCTYPE author [",
|
||||
"<!ELEMENT book ANY>",
|
||||
"<!ENTITY js SYSTEM \"/etc/passwd\">",
|
||||
"]>",
|
||||
"<bookstore>",
|
||||
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||
"</bookstore>"
|
||||
]
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRequestBodyAccess On",
|
||||
"SecParseXmlIntoArgs On",
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||
"SecRule ARGS_GET:q \"@rx xml\" \"id:500012,phase:1,t:none,t:lowercase,ctl:parseXmlIntoArgs=Off\"",
|
||||
"SecRule XML:/* \"@rx aaa\" \"id:500013,phase:2,t:none,t:lowercase,log,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"resource":"libxml2",
|
||||
"title":"Testing XML parsing to ARGS with On, turn OnlyArgs with ctl, check ARGS",
|
||||
"expected":{
|
||||
"http_code": 403
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"Content-Type": "text/xml"
|
||||
},
|
||||
"uri":"/?q=xml",
|
||||
"method":"POST",
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
||||
"<!DOCTYPE author [",
|
||||
"<!ELEMENT book ANY>",
|
||||
"<!ENTITY js SYSTEM \"/etc/passwd\">",
|
||||
"]>",
|
||||
"<bookstore>",
|
||||
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||
"</bookstore>"
|
||||
]
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRequestBodyAccess On",
|
||||
"SecParseXmlIntoArgs On",
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||
"SecRule ARGS_GET:q \"@rx xml\" \"id:500012,phase:1,t:none,t:lowercase,ctl:parseXmlIntoArgs=OnlyArgs\"",
|
||||
"SecRule ARGS:xml.bookstore.some-tag \"@rx aaa\" \"id:500013,phase:2,t:none,t:lowercase,log,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"resource":"libxml2",
|
||||
"title":"Testing XML parsing to ARGS with On, turn OnlyArgs with ctl, check XML",
|
||||
"expected":{
|
||||
"http_code": 200
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"Content-Type": "text/xml"
|
||||
},
|
||||
"uri":"/?q=xml",
|
||||
"method":"POST",
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
||||
"<!DOCTYPE author [",
|
||||
"<!ELEMENT book ANY>",
|
||||
"<!ENTITY js SYSTEM \"/etc/passwd\">",
|
||||
"]>",
|
||||
"<bookstore>",
|
||||
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||
"</bookstore>"
|
||||
]
|
||||
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRequestBodyAccess On",
|
||||
"SecParseXmlIntoArgs On",
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||
"SecRule ARGS_GET:q \"@rx xml\" \"id:500012,phase:1,t:none,t:lowercase,ctl:parseXmlIntoArgs=OnlyArgs\"",
|
||||
"SecRule XML:/* \"@rx aaa\" \"id:500013,phase:2,t:none,t:lowercase,log,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"resource":"libxml2",
|
||||
"title":"Testing XML parsing to ARGS with Off, turn On with ctl, check ARGS",
|
||||
"expected":{
|
||||
"http_code": 403
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"Content-Type": "text/xml"
|
||||
},
|
||||
"uri":"/?q=xml",
|
||||
"method":"POST",
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
||||
"<!DOCTYPE author [",
|
||||
"<!ELEMENT book ANY>",
|
||||
"<!ENTITY js SYSTEM \"/etc/passwd\">",
|
||||
"]>",
|
||||
"<bookstore>",
|
||||
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||
"</bookstore>"
|
||||
]
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRequestBodyAccess On",
|
||||
"SecParseXmlIntoArgs Off",
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||
"SecRule ARGS_GET:q \"@rx xml\" \"id:500012,phase:1,t:none,t:lowercase,ctl:parseXmlIntoArgs=On\"",
|
||||
"SecRule ARGS:xml.bookstore.some-tag \"@rx aaa\" \"id:500013,phase:2,t:none,t:lowercase,log,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"resource":"libxml2",
|
||||
"title":"Testing XML parsing to ARGS with Off, turn On with ctl, check XML",
|
||||
"expected":{
|
||||
"http_code": 403
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"Content-Type": "text/xml"
|
||||
},
|
||||
"uri":"/?q=xml",
|
||||
"method":"POST",
|
||||
"body": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
||||
"<!DOCTYPE author [",
|
||||
"<!ELEMENT book ANY>",
|
||||
"<!ENTITY js SYSTEM \"/etc/passwd\">",
|
||||
"]>",
|
||||
"<bookstore>",
|
||||
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||
"</bookstore>"
|
||||
]
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRequestBodyAccess On",
|
||||
"SecParseXmlIntoArgs Off",
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||
"SecRule ARGS_GET:q \"@rx xml\" \"id:500012,phase:1,t:none,t:lowercase,ctl:parseXmlIntoArgs=On\"",
|
||||
"SecRule XML:/* \"@rx aaa\" \"id:500013,phase:2,t:none,t:lowercase,log,deny,status:403\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled":1,
|
||||
"version_min":300000,
|
||||
"resource":"libxml2",
|
||||
"title":"Testing XML parsing to ARGS with On, node contains utf8 character",
|
||||
"expected":{
|
||||
"http_code": 403
|
||||
},
|
||||
"client":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":123
|
||||
},
|
||||
"request":{
|
||||
"headers":{
|
||||
"Host":"localhost",
|
||||
"User-Agent":"curl/7.38.0",
|
||||
"Accept":"*/*",
|
||||
"Content-Type": "text/xml"
|
||||
},
|
||||
"uri":"/?q=xml",
|
||||
"method":"POST",
|
||||
"body": [
|
||||
"<pizza>",
|
||||
"<has>pineapple</has><has>🍍</has>",
|
||||
"</pizza>"
|
||||
]
|
||||
},
|
||||
"server":{
|
||||
"ip":"200.249.12.31",
|
||||
"port":80
|
||||
},
|
||||
"rules":[
|
||||
"SecRuleEngine On",
|
||||
"SecRequestBodyAccess On",
|
||||
"SecParseXmlIntoArgs On",
|
||||
"SecRule REQUEST_HEADERS:Content-Type \"^text/xml$\" \"id:500011,phase:1,t:none,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML\"",
|
||||
"SecRule ARGS \"@rx 🍍\" \"id:500013,phase:2,t:none,t:lowercase,log,deny,status:403\""
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -86,6 +86,7 @@ TESTS+=test/test-cases/regression/operator-fuzzyhash.json
|
||||
TESTS+=test/test-cases/regression/operator-inpectFile.json
|
||||
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-rxGlobal.json
|
||||
TESTS+=test/test-cases/regression/operator-UnconditionalMatch.json
|
||||
|
@ -15,6 +15,7 @@ modsec_rules_check_LDADD = \
|
||||
$(LMDB_LDADD) \
|
||||
$(LUA_LDADD) \
|
||||
$(PCRE_LDADD) \
|
||||
$(PCRE2_LDADD) \
|
||||
$(SSDEEP_LDADD) \
|
||||
$(YAJL_LDADD)
|
||||
|
||||
@ -25,12 +26,14 @@ modsec_rules_check_LDFLAGS = \
|
||||
$(LMDB_LDFLAGS) \
|
||||
$(LUA_LDFLAGS) \
|
||||
$(SSDEEP_LDFLAGS) \
|
||||
$(YAJL_LDFLAGS)
|
||||
$(YAJL_LDFLAGS) \
|
||||
$(LIBXML2_LDFLAGS)
|
||||
|
||||
modsec_rules_check_CPPFLAGS = \
|
||||
-I$(top_builddir)/headers \
|
||||
$(GLOBAL_CPPFLAGS) \
|
||||
$(PCRE_CFLAGS) \
|
||||
$(PCRE2_CFLAGS) \
|
||||
$(LMDB_CFLAGS) \
|
||||
$(MAXMIND_CFLAGS) \
|
||||
$(LIBXML2_CFLAGS)
|
||||
|
Loading…
x
Reference in New Issue
Block a user