mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 05:45:59 +03:00
Merge pull request #3363 from airween/v3/xmlargsfeat
feat: improved XMLArgs processing
This commit is contained in:
commit
220caa5abc
@ -52,6 +52,11 @@
|
|||||||
to = (from == PropertyNotSetBodyLimitAction) ? default : from; \
|
to = (from == PropertyNotSetBodyLimitAction) ? default : from; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define merge_xmlargparse_value(to, from, default) \
|
||||||
|
if (to == PropertyNotSetConfigXMLParseXmlIntoArgs) { \
|
||||||
|
to = (from == PropertyNotSetConfigXMLParseXmlIntoArgs) ? default : from; \
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
namespace modsecurity {
|
namespace modsecurity {
|
||||||
@ -177,6 +182,7 @@ class RulesSetProperties {
|
|||||||
m_secRequestBodyAccess(PropertyNotSetConfigBoolean),
|
m_secRequestBodyAccess(PropertyNotSetConfigBoolean),
|
||||||
m_secResponseBodyAccess(PropertyNotSetConfigBoolean),
|
m_secResponseBodyAccess(PropertyNotSetConfigBoolean),
|
||||||
m_secXMLExternalEntity(PropertyNotSetConfigBoolean),
|
m_secXMLExternalEntity(PropertyNotSetConfigBoolean),
|
||||||
|
m_secXMLParseXmlIntoArgs(PropertyNotSetConfigXMLParseXmlIntoArgs),
|
||||||
m_tmpSaveUploadedFiles(PropertyNotSetConfigBoolean),
|
m_tmpSaveUploadedFiles(PropertyNotSetConfigBoolean),
|
||||||
m_uploadKeepFiles(PropertyNotSetConfigBoolean),
|
m_uploadKeepFiles(PropertyNotSetConfigBoolean),
|
||||||
m_debugLog(new DebugLog()),
|
m_debugLog(new DebugLog()),
|
||||||
@ -191,6 +197,7 @@ class RulesSetProperties {
|
|||||||
m_secRequestBodyAccess(PropertyNotSetConfigBoolean),
|
m_secRequestBodyAccess(PropertyNotSetConfigBoolean),
|
||||||
m_secResponseBodyAccess(PropertyNotSetConfigBoolean),
|
m_secResponseBodyAccess(PropertyNotSetConfigBoolean),
|
||||||
m_secXMLExternalEntity(PropertyNotSetConfigBoolean),
|
m_secXMLExternalEntity(PropertyNotSetConfigBoolean),
|
||||||
|
m_secXMLParseXmlIntoArgs(PropertyNotSetConfigXMLParseXmlIntoArgs),
|
||||||
m_tmpSaveUploadedFiles(PropertyNotSetConfigBoolean),
|
m_tmpSaveUploadedFiles(PropertyNotSetConfigBoolean),
|
||||||
m_uploadKeepFiles(PropertyNotSetConfigBoolean),
|
m_uploadKeepFiles(PropertyNotSetConfigBoolean),
|
||||||
m_debugLog(debugLog),
|
m_debugLog(debugLog),
|
||||||
@ -218,7 +225,8 @@ class RulesSetProperties {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
* The ConfigBoolean enumerator defines the states for configuration boolean values.
|
||||||
|
* The default value is PropertyNotSetConfigBoolean.
|
||||||
*/
|
*/
|
||||||
enum ConfigBoolean {
|
enum ConfigBoolean {
|
||||||
TrueConfigBoolean,
|
TrueConfigBoolean,
|
||||||
@ -226,6 +234,18 @@ class RulesSetProperties {
|
|||||||
PropertyNotSetConfigBoolean
|
PropertyNotSetConfigBoolean
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* The ConfigXMLParseXmlIntoArgs enumerator defines the states for the configuration
|
||||||
|
* XMLParseXmlIntoArgs values.
|
||||||
|
* The default value is PropertyNotSetConfigXMLParseXmlIntoArgs.
|
||||||
|
*/
|
||||||
|
enum ConfigXMLParseXmlIntoArgs {
|
||||||
|
TrueConfigXMLParseXmlIntoArgs,
|
||||||
|
FalseConfigXMLParseXmlIntoArgs,
|
||||||
|
OnlyArgsConfigXMLParseXmlIntoArgs,
|
||||||
|
PropertyNotSetConfigXMLParseXmlIntoArgs
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -338,6 +358,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,
|
static int mergeProperties(RulesSetProperties *from,
|
||||||
RulesSetProperties *to, std::ostringstream *err) {
|
RulesSetProperties *to, std::ostringstream *err) {
|
||||||
@ -357,6 +390,10 @@ class RulesSetProperties {
|
|||||||
from->m_secXMLExternalEntity,
|
from->m_secXMLExternalEntity,
|
||||||
PropertyNotSetConfigBoolean);
|
PropertyNotSetConfigBoolean);
|
||||||
|
|
||||||
|
merge_xmlargparse_value(to->m_secXMLParseXmlIntoArgs,
|
||||||
|
from->m_secXMLParseXmlIntoArgs,
|
||||||
|
PropertyNotSetConfigXMLParseXmlIntoArgs);
|
||||||
|
|
||||||
merge_boolean_value(to->m_uploadKeepFiles,
|
merge_boolean_value(to->m_uploadKeepFiles,
|
||||||
from->m_uploadKeepFiles,
|
from->m_uploadKeepFiles,
|
||||||
PropertyNotSetConfigBoolean);
|
PropertyNotSetConfigBoolean);
|
||||||
@ -464,6 +501,7 @@ class RulesSetProperties {
|
|||||||
ConfigBoolean m_secRequestBodyAccess;
|
ConfigBoolean m_secRequestBodyAccess;
|
||||||
ConfigBoolean m_secResponseBodyAccess;
|
ConfigBoolean m_secResponseBodyAccess;
|
||||||
ConfigBoolean m_secXMLExternalEntity;
|
ConfigBoolean m_secXMLExternalEntity;
|
||||||
|
ConfigXMLParseXmlIntoArgs m_secXMLParseXmlIntoArgs;
|
||||||
ConfigBoolean m_tmpSaveUploadedFiles;
|
ConfigBoolean m_tmpSaveUploadedFiles;
|
||||||
ConfigBoolean m_uploadKeepFiles;
|
ConfigBoolean m_uploadKeepFiles;
|
||||||
ConfigDouble m_argumentsLimit;
|
ConfigDouble m_argumentsLimit;
|
||||||
|
@ -619,6 +619,7 @@ class Transaction : public TransactionAnchoredVariables, public TransactionSecMa
|
|||||||
RequestBodyProcessor::JSON *m_json;
|
RequestBodyProcessor::JSON *m_json;
|
||||||
|
|
||||||
int m_secRuleEngine;
|
int m_secRuleEngine;
|
||||||
|
int m_secXMLParseXmlIntoArgs;
|
||||||
|
|
||||||
std::string m_variableDuration;
|
std::string m_variableDuration;
|
||||||
std::map<std::string, std::string> m_variableEnvs;
|
std::map<std::string, std::string> m_variableEnvs;
|
||||||
|
@ -119,6 +119,7 @@ ACTIONS = \
|
|||||||
actions/chain.cc \
|
actions/chain.cc \
|
||||||
actions/ctl/audit_log_parts.cc \
|
actions/ctl/audit_log_parts.cc \
|
||||||
actions/ctl/audit_engine.cc \
|
actions/ctl/audit_engine.cc \
|
||||||
|
actions/ctl/parse_xml_into_args.cc \
|
||||||
actions/ctl/rule_engine.cc \
|
actions/ctl/rule_engine.cc \
|
||||||
actions/ctl/request_body_processor_json.cc \
|
actions/ctl/request_body_processor_json.cc \
|
||||||
actions/ctl/request_body_processor_xml.cc \
|
actions/ctl/request_body_processor_xml.cc \
|
||||||
|
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_
|
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/chain.h"
|
||||||
#include "src/actions/ctl/audit_engine.h"
|
#include "src/actions/ctl/audit_engine.h"
|
||||||
#include "src/actions/ctl/audit_log_parts.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/request_body_access.h"
|
||||||
#include "src/actions/ctl/rule_engine.h"
|
#include "src/actions/ctl/rule_engine.h"
|
||||||
#include "src/actions/ctl/request_body_processor_json.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_CC "OPERATOR_VERIFY_CC"
|
||||||
OPERATOR_VERIFY_CPF "OPERATOR_VERIFY_CPF"
|
OPERATOR_VERIFY_CPF "OPERATOR_VERIFY_CPF"
|
||||||
OPERATOR_VERIFY_SSN "OPERATOR_VERIFY_SSN"
|
OPERATOR_VERIFY_SSN "OPERATOR_VERIFY_SSN"
|
||||||
OPERATOR_VERIFY_SVNR "OPERATOR_VERIFY_SVNR"
|
OPERATOR_VERIFY_SVNR "OPERATOR_VERIFY_SVNR"
|
||||||
OPERATOR_WITHIN "OPERATOR_WITHIN"
|
OPERATOR_WITHIN "OPERATOR_WITHIN"
|
||||||
|
|
||||||
CONFIG_DIR_AUDIT_LOG_FMT
|
CONFIG_DIR_AUDIT_LOG_FMT
|
||||||
@ -502,6 +503,7 @@ using namespace modsecurity::operators;
|
|||||||
ACTION_CTL_BDY_XML "ACTION_CTL_BDY_XML"
|
ACTION_CTL_BDY_XML "ACTION_CTL_BDY_XML"
|
||||||
ACTION_CTL_BDY_URLENCODED "ACTION_CTL_BDY_URLENCODED"
|
ACTION_CTL_BDY_URLENCODED "ACTION_CTL_BDY_URLENCODED"
|
||||||
ACTION_CTL_FORCE_REQ_BODY_VAR "ACTION_CTL_FORCE_REQ_BODY_VAR"
|
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_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_ID "ACTION_CTL_RULE_REMOVE_BY_ID"
|
||||||
ACTION_CTL_RULE_REMOVE_BY_TAG "ACTION_CTL_RULE_REMOVE_BY_TAG"
|
ACTION_CTL_RULE_REMOVE_BY_TAG "ACTION_CTL_RULE_REMOVE_BY_TAG"
|
||||||
@ -649,6 +651,7 @@ using namespace modsecurity::operators;
|
|||||||
CONFIG_VALUE_ABORT "CONFIG_VALUE_ABORT"
|
CONFIG_VALUE_ABORT "CONFIG_VALUE_ABORT"
|
||||||
CONFIG_VALUE_DETC "CONFIG_VALUE_DETC"
|
CONFIG_VALUE_DETC "CONFIG_VALUE_DETC"
|
||||||
CONFIG_VALUE_HTTPS "CONFIG_VALUE_HTTPS"
|
CONFIG_VALUE_HTTPS "CONFIG_VALUE_HTTPS"
|
||||||
|
CONFIG_VALUE_ONLYARGS "CONFIG_VALUE_ONLYARGS"
|
||||||
CONFIG_VALUE_OFF "CONFIG_VALUE_OFF"
|
CONFIG_VALUE_OFF "CONFIG_VALUE_OFF"
|
||||||
CONFIG_VALUE_ON "CONFIG_VALUE_ON"
|
CONFIG_VALUE_ON "CONFIG_VALUE_ON"
|
||||||
CONFIG_VALUE_PARALLEL "CONFIG_VALUE_PARALLEL"
|
CONFIG_VALUE_PARALLEL "CONFIG_VALUE_PARALLEL"
|
||||||
@ -658,6 +661,7 @@ using namespace modsecurity::operators;
|
|||||||
CONFIG_VALUE_SERIAL "CONFIG_VALUE_SERIAL"
|
CONFIG_VALUE_SERIAL "CONFIG_VALUE_SERIAL"
|
||||||
CONFIG_VALUE_WARN "CONFIG_VALUE_WARN"
|
CONFIG_VALUE_WARN "CONFIG_VALUE_WARN"
|
||||||
CONFIG_XML_EXTERNAL_ENTITY "CONFIG_XML_EXTERNAL_ENTITY"
|
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_RESPONSE_BODY_MP "CONGIG_DIR_RESPONSE_BODY_MP"
|
||||||
CONGIG_DIR_SEC_ARG_SEP "CONGIG_DIR_SEC_ARG_SEP"
|
CONGIG_DIR_SEC_ARG_SEP "CONGIG_DIR_SEC_ARG_SEP"
|
||||||
CONGIG_DIR_SEC_COOKIE_FORMAT "CONGIG_DIR_SEC_COOKIE_FORMAT"
|
CONGIG_DIR_SEC_COOKIE_FORMAT "CONGIG_DIR_SEC_COOKIE_FORMAT"
|
||||||
@ -1686,6 +1690,18 @@ expression:
|
|||||||
{
|
{
|
||||||
driver.m_secXMLExternalEntity = modsecurity::RulesSetProperties::TrueConfigBoolean;
|
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
|
| CONGIG_DIR_SEC_TMP_DIR
|
||||||
{
|
{
|
||||||
/* Parser error disabled to avoid breaking default installations with modsecurity.conf-recommended
|
/* Parser error disabled to avoid breaking default installations with modsecurity.conf-recommended
|
||||||
@ -2696,6 +2712,18 @@ act:
|
|||||||
//ACTION_NOT_SUPPORTED("CtlForceReequestBody", @0);
|
//ACTION_NOT_SUPPORTED("CtlForceReequestBody", @0);
|
||||||
ACTION_CONTAINER($$, new actions::Action($1));
|
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_CTL_REQUEST_BODY_ACCESS CONFIG_VALUE_ON
|
||||||
{
|
{
|
||||||
ACTION_CONTAINER($$, new actions::ctl::RequestBodyAccess($1 + "true"));
|
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_XML (?i:ctl:requestBodyProcessor=XML)
|
||||||
ACTION_CTL_BDY_URLENCODED (?i:ctl:requestBodyProcessor=URLENCODED)
|
ACTION_CTL_BDY_URLENCODED (?i:ctl:requestBodyProcessor=URLENCODED)
|
||||||
ACTION_CTL_FORCE_REQ_BODY_VAR (?i:ctl:forceRequestBodyVariable)
|
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_REQUEST_BODY_ACCESS (?i:ctl:requestBodyAccess)
|
||||||
ACTION_CTL_RULE_ENGINE (?i:ctl:ruleEngine)
|
ACTION_CTL_RULE_ENGINE (?i:ctl:ruleEngine)
|
||||||
ACTION_CTL_RULE_REMOVE_BY_TAG (?i:ctl:ruleRemoveByTag)
|
ACTION_CTL_RULE_REMOVE_BY_TAG (?i:ctl:ruleRemoveByTag)
|
||||||
@ -400,6 +401,7 @@ CONFIG_VALUE_ABORT (?i:Abort)
|
|||||||
CONFIG_VALUE_DETC (?i:DetectionOnly)
|
CONFIG_VALUE_DETC (?i:DetectionOnly)
|
||||||
CONFIG_VALUE_HTTPS (?i:https)
|
CONFIG_VALUE_HTTPS (?i:https)
|
||||||
CONFIG_VALUE_NUMBER [0-9]+
|
CONFIG_VALUE_NUMBER [0-9]+
|
||||||
|
CONFIG_VALUE_ONLYARGS (?i:OnlyArgs)
|
||||||
CONFIG_VALUE_OFF (?i:Off)
|
CONFIG_VALUE_OFF (?i:Off)
|
||||||
CONFIG_VALUE_ON (?i:On)
|
CONFIG_VALUE_ON (?i:On)
|
||||||
CONFIG_VALUE_PARALLEL (?i:Parallel|Concurrent)
|
CONFIG_VALUE_PARALLEL (?i:Parallel|Concurrent)
|
||||||
@ -410,6 +412,7 @@ CONFIG_VALUE_RELEVANT_ONLY (?i:RelevantOnly)
|
|||||||
CONFIG_VALUE_SERIAL (?i:Serial)
|
CONFIG_VALUE_SERIAL (?i:Serial)
|
||||||
CONFIG_VALUE_WARN (?i:Warn)
|
CONFIG_VALUE_WARN (?i:Warn)
|
||||||
CONFIG_XML_EXTERNAL_ENTITY (?i:SecXmlExternalEntity)
|
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 (?i:SecResponseBodyMimeType)
|
||||||
CONGIG_DIR_RESPONSE_BODY_MP_CLEAR (?i:SecResponseBodyMimeTypesClear)
|
CONGIG_DIR_RESPONSE_BODY_MP_CLEAR (?i:SecResponseBodyMimeTypesClear)
|
||||||
CONGIG_DIR_SEC_ARG_SEP (?i:SecArgumentSeparator)
|
CONGIG_DIR_SEC_ARG_SEP (?i:SecArgumentSeparator)
|
||||||
@ -537,6 +540,7 @@ EQUALS_MINUS (?i:=\-)
|
|||||||
{ACTION_CTL_BDY_XML} { return p::make_ACTION_CTL_BDY_XML(yytext, *driver.loc.back()); }
|
{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_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_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_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_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()); }
|
{ACTION_CTL_RULE_REMOVE_BY_ID}[=]{REMOVE_RULE_BY} { return p::make_ACTION_CTL_RULE_REMOVE_BY_ID(yytext, *driver.loc.back()); }
|
||||||
@ -609,6 +613,7 @@ EQUALS_MINUS (?i:=\-)
|
|||||||
{ACTION_LOG_DATA}: { BEGIN(EXPECTING_ACTION_PREDICATE); return p::make_ACTION_LOG_DATA(yytext, *driver.loc.back()); }
|
{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_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_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_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()); }
|
{CONFIG_VALUE_RELEVANT_ONLY} { return p::make_CONFIG_VALUE_RELEVANT_ONLY(yytext, *driver.loc.back()); }
|
||||||
@ -805,6 +810,7 @@ EQUALS_MINUS (?i:=\-)
|
|||||||
{CONFIG_VALUE_ABORT} { return p::make_CONFIG_VALUE_ABORT(yytext, *driver.loc.back()); }
|
{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_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_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_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_ON} { return p::make_CONFIG_VALUE_ON(yytext, *driver.loc.back()); }
|
||||||
{CONFIG_VALUE_PARALLEL} { return p::make_CONFIG_VALUE_PARALLEL(yytext, *driver.loc.back()); }
|
{CONFIG_VALUE_PARALLEL} { return p::make_CONFIG_VALUE_PARALLEL(yytext, *driver.loc.back()); }
|
||||||
@ -814,6 +820,7 @@ EQUALS_MINUS (?i:=\-)
|
|||||||
{CONFIG_VALUE_SERIAL} { return p::make_CONFIG_VALUE_SERIAL(yytext, *driver.loc.back()); }
|
{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_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_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}[ \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_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()); }
|
{CONGIG_DIR_SEC_ARG_SEP}[ \t]+{FREE_TEXT_NEW_LINE} { return p::make_CONGIG_DIR_SEC_ARG_SEP(yytext, *driver.loc.back()); }
|
||||||
|
@ -25,11 +25,138 @@ namespace RequestBodyProcessor {
|
|||||||
|
|
||||||
#ifdef WITH_LIBXML2
|
#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)
|
XML::XML(Transaction *transaction)
|
||||||
: m_transaction(transaction) {
|
: m_transaction(transaction) {
|
||||||
m_data.doc = NULL;
|
m_data.doc = NULL;
|
||||||
m_data.parsing_ctx = NULL;
|
m_data.parsing_ctx = NULL;
|
||||||
m_data.sax_handler = 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() {
|
bool XML::init() {
|
||||||
//xmlParserInputBufferCreateFilenameFunc entity;
|
//xmlParserInputBufferCreateFilenameFunc entity;
|
||||||
if (m_transaction->m_rules->m_secXMLExternalEntity
|
if (m_transaction->m_rules->m_secXMLExternalEntity
|
||||||
@ -55,6 +181,28 @@ bool XML::init() {
|
|||||||
/*entity = */xmlParserInputBufferCreateFilenameDefault(
|
/*entity = */xmlParserInputBufferCreateFilenameDefault(
|
||||||
this->unloadExternalEntity);
|
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;
|
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
|
* enable us to pass it the first chunk of data so that
|
||||||
* it can attempt to auto-detect the encoding.
|
* 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. */
|
/* First invocation. */
|
||||||
|
|
||||||
ms_dbg_a(m_transaction, 4, "XML: Initialising parser.");
|
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,
|
if (m_transaction->m_secXMLParseXmlIntoArgs
|
||||||
buf, size, "body.xml");
|
!= RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs) {
|
||||||
|
m_data.parsing_ctx = xmlCreatePushParserCtxt(NULL, NULL,
|
||||||
|
buf, size, "body.xml");
|
||||||
|
|
||||||
if (m_data.parsing_ctx == NULL) {
|
if (m_data.parsing_ctx == NULL) {
|
||||||
ms_dbg_a(m_transaction, 4,
|
ms_dbg_a(m_transaction, 4,
|
||||||
"XML: Failed to create parsing context.");
|
"XML: Failed to create parsing context.");
|
||||||
error->assign("XML: Failed to create parsing context.");
|
error->assign("XML: Failed to create parsing context.");
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not a first invocation. */
|
/* Not a first invocation. */
|
||||||
xmlParseChunk(m_data.parsing_ctx, buf, size, 0);
|
if (m_data.parsing_ctx != NULL &&
|
||||||
if (m_data.parsing_ctx->wellFormed != 1) {
|
m_transaction->m_secXMLParseXmlIntoArgs
|
||||||
error->assign("XML: Failed to create parsing context.");
|
!= RulesSetProperties::OnlyArgsConfigXMLParseXmlIntoArgs) {
|
||||||
ms_dbg_a(m_transaction, 4, "XML: Failed parsing document.");
|
xmlSetGenericErrorFunc(m_data.parsing_ctx, null_error);
|
||||||
return false;
|
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;
|
return true;
|
||||||
@ -119,24 +307,51 @@ bool XML::processChunk(const char *buf, unsigned int size,
|
|||||||
|
|
||||||
bool XML::complete(std::string *error) {
|
bool XML::complete(std::string *error) {
|
||||||
/* Only if we have a context, meaning we've done some work. */
|
/* Only if we have a context, meaning we've done some work. */
|
||||||
if (m_data.parsing_ctx != NULL) {
|
if (m_data.parsing_ctx != NULL || m_data.parsing_ctx_arg != NULL) {
|
||||||
/* This is how we signalise the end of parsing to libxml. */
|
if (m_data.parsing_ctx != NULL &&
|
||||||
xmlParseChunk(m_data.parsing_ctx, NULL, 0, 1);
|
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. */
|
/* Preserve the results for our reference. */
|
||||||
m_data.well_formed = m_data.parsing_ctx->wellFormed;
|
m_data.well_formed = m_data.parsing_ctx->wellFormed;
|
||||||
m_data.doc = m_data.parsing_ctx->myDoc;
|
m_data.doc = m_data.parsing_ctx->myDoc;
|
||||||
|
|
||||||
/* Clean up everything else. */
|
/* Clean up everything else. */
|
||||||
xmlFreeParserCtxt(m_data.parsing_ctx);
|
xmlFreeParserCtxt(m_data.parsing_ctx);
|
||||||
m_data.parsing_ctx = NULL;
|
m_data.parsing_ctx = NULL;
|
||||||
ms_dbg_a(m_transaction, 4, "XML: Parsing complete (well_formed " \
|
ms_dbg_a(m_transaction, 4, "XML: Parsing complete (well_formed " \
|
||||||
+ std::to_string(m_data.well_formed) + ").");
|
+ std::to_string(m_data.well_formed) + ").");
|
||||||
|
|
||||||
if (m_data.well_formed != 1) {
|
if (m_data.well_formed != 1) {
|
||||||
error->assign("XML: Failed parsing document.");
|
error->assign("XML: Failed to parse document.");
|
||||||
ms_dbg_a(m_transaction, 4, "XML: Failed parsing document.");
|
ms_dbg_a(m_transaction, 4, "XML: Failed to parse document.");
|
||||||
return false;
|
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
|
#ifdef WITH_LIBXML2
|
||||||
#include <libxml/xmlschemas.h>
|
#include <libxml/xmlschemas.h>
|
||||||
#include <libxml/xpath.h>
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/SAX.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -33,12 +34,51 @@ namespace RequestBodyProcessor {
|
|||||||
|
|
||||||
#ifdef WITH_LIBXML2
|
#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 {
|
struct xml_data {
|
||||||
xmlSAXHandler *sax_handler;
|
std::unique_ptr<xmlSAXHandler> sax_handler;
|
||||||
xmlParserCtxtPtr parsing_ctx;
|
xmlParserCtxtPtr parsing_ctx;
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
|
|
||||||
unsigned int well_formed;
|
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;
|
typedef struct xml_data xml_data;
|
||||||
|
@ -148,6 +148,7 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, const char *id,
|
|||||||
m_json(nullptr),
|
m_json(nullptr),
|
||||||
#endif
|
#endif
|
||||||
m_secRuleEngine(RulesSetProperties::PropertyNotSetRuleEngine),
|
m_secRuleEngine(RulesSetProperties::PropertyNotSetRuleEngine),
|
||||||
|
m_secXMLParseXmlIntoArgs(rules->m_secXMLParseXmlIntoArgs),
|
||||||
m_logCbData(logCbData),
|
m_logCbData(logCbData),
|
||||||
TransactionAnchoredVariables(this) {
|
TransactionAnchoredVariables(this) {
|
||||||
m_variableUrlEncodedError.set("0", 0);
|
m_variableUrlEncodedError.set("0", 0);
|
||||||
|
@ -144,7 +144,7 @@
|
|||||||
"resource":"libxml2",
|
"resource":"libxml2",
|
||||||
"title":"Testing CtlRequestBodyProcessor=XML (3)",
|
"title":"Testing CtlRequestBodyProcessor=XML (3)",
|
||||||
"expected":{
|
"expected":{
|
||||||
"debug_log": "XML: Failed parsing document."
|
"debug_log": "XML: Failed to parse document."
|
||||||
},
|
},
|
||||||
"client":{
|
"client":{
|
||||||
"ip":"200.249.12.31",
|
"ip":"200.249.12.31",
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"expected":{
|
"expected":{
|
||||||
"debug_log":"XML parsing error: XML: Failed parsing document"
|
"debug_log":"XML parsing error: XML: Failed to parse document"
|
||||||
},
|
},
|
||||||
"rules":[
|
"rules":[
|
||||||
"SecRuleEngine On",
|
"SecRuleEngine On",
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
"<some-tag>aaa</some-tag><some-tag>bbb</some-tag>",
|
||||||
"</bookstore>"
|
"</bookstore>"
|
||||||
]
|
]
|
||||||
|
|
||||||
},
|
},
|
||||||
"server":{
|
"server":{
|
||||||
"ip":"200.249.12.31",
|
"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 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\""
|
"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\""
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user