diff --git a/headers/modsecurity/assay.h b/headers/modsecurity/assay.h index fa3ac059..642b998e 100644 --- a/headers/modsecurity/assay.h +++ b/headers/modsecurity/assay.h @@ -95,6 +95,64 @@ class ModSecurityCollectionsVariables : class ModSecurityStringVariables : public std::unordered_multimap { public: + void storeVariable(std::string key, std::string value) { + this->emplace(key, value); + } + + bool storeOrUpdateVariable(const std::string &key, + const std::string &value) { + if (updateFirstVariable(key, value) == false) { + storeVariable(key, value); + } + } + + + bool updateFirstVariable(const std::string &key, const std::string &value) { + auto range = this->equal_range(key); + + for (auto it = range.first; it != range.second; ++it) { + it->second = value; + return true; + } + return false; + } + + + void deleteVariable(const std::string& key) { + this->erase(key); + } + + + std::list> + resolveVariable(const std::string& key) { + std::list> l; + std::pair pair; + + auto range = this->equal_range(key); + + for (auto it = range.first; it != range.second; ++it) { + pair = std::make_pair(std::string(key), std::string(it->second)); + l.push_back(pair); + } + + if (l.size() == 0) { + for (auto& x : *this) { + if ((x.first.substr(0, key.size() + 1).compare(key + ":") != 0) + && (x.first != key)) { + continue; + } + std::list> t; + t = this->resolveVariable(x.first); + for (std::pair z : t) { + pair = std::make_pair(std::string(z.first), + std::string(z.second)); + l.push_back(pair); + } + } + } + + return l; + } }; /** @ingroup ModSecurity_CPP_API */ @@ -160,18 +218,25 @@ class Assay { void cleanup(); + void setCollection(const std::string& collectionName, + const std::string& variableName, + const std::string& targetValue); + const char *getResponseBody(); int getResponseBodyLenth(); std::list> resolve_variable(std::string var); std::string* resolve_variable_first(std::string); + std::string* resolve_variable_first(const std::string collectionName, + std::string var); void store_variable(std::string, const std::string &value); bool update_variable_first(std::string var, const std::string &value); void delete_variable(std::string key); ModSecurityStringVariables m_variables_strings; + std::unordered_map collections; void debug(int, std::string); std::vector actions; diff --git a/src/Makefile.am b/src/Makefile.am index 1948b2ed..4c7b7998 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -61,6 +61,7 @@ ACTIONS = \ actions/redirect.cc \ actions/rule_id.cc \ actions/severity.cc \ + actions/set_var.cc \ actions/status.cc \ actions/transformations/base64_decode.cc \ actions/transformations/base64_decode_ext.cc \ @@ -123,6 +124,7 @@ libmodsecurity_la_SOURCES = \ rules.cc \ utils.cc \ debug_log.cc \ + macro_expansion.cc \ request_body_processor/multipart.cc \ request_body_processor/multipart_blob.cc \ rule.cc \ diff --git a/src/actions/action.h b/src/actions/action.h index 31759b0b..3b9deda6 100644 --- a/src/actions/action.h +++ b/src/actions/action.h @@ -35,11 +35,17 @@ class Action { explicit Action(const std::string& _action) : action_kind(2), action(_action), - temporaryAction(false) { } + name(_action), + temporaryAction(false) { + name.erase(0, 2); + } explicit Action(const std::string& _action, int kind) : action_kind(kind), action(_action), - temporaryAction(false) { } + name(_action), + temporaryAction(false) { + name.erase(0, 2); + } virtual ~Action() { } /** diff --git a/src/actions/set_var.cc b/src/actions/set_var.cc new file mode 100644 index 00000000..be60027c --- /dev/null +++ b/src/actions/set_var.cc @@ -0,0 +1,140 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include "actions/set_var.h" + +#include +#include + +#include "modsecurity/assay.h" +#include "src/rule.h" + +namespace ModSecurity { +namespace actions { + +SetVar::SetVar(std::string action) + : Action(action, RunTimeOnlyIfMatchKind) { +} + + +bool SetVar::init(std::string *error) { + size_t pos = std::string::npos; + + // Resolv operation + operation = setToOne; + pos = action.find("="); + if (pos != std::string::npos) { + operation = setOperation; + } + pos = action.find("=+"); + if (pos != std::string::npos) { + operation = sumAndSetOperation; + } + pos = action.find("=-"); + if (pos != std::string::npos) { + operation = substractAndSetOperation; + } + + // Collection name + pos = action.find("."); + if (pos != std::string::npos) { + collectionName = std::string(action, 0, pos); + } else { + error->assign("Missing the collection and/or variable name"); + return false; + } + + // Variable name + if (operation == setToOne) { + variableName = std::string(action, pos + 1, action.length() + - (pos + 1)); + } else { + size_t pos2 = action.find("="); + variableName = std::string(action, pos + 1, pos2 - (pos + 1)); + if (pos2 + 2 > action.length()) { + error->assign("Something wrong with the input format"); + return false; + } + + if (operation == setOperation) { + predicate = std::string(action, pos2 + 1, action.length() - (pos2)); + } else { + predicate = std::string(action, pos2 + 2, action.length() + - (pos2 + 1)); + } + } + + if (collectionName.empty() || variableName.empty()) { + error->assign("Something wrong with the input format"); + return false; + } + + return true; +} + +void SetVar::dump() { + std::cout << " Operation: " << std::to_string(operation) << std::endl; + std::cout << "Collection: " << collectionName << std::endl; + std::cout << " Variable: " << variableName << std::endl; + std::cout << " Predicate: " << predicate << std::endl; +} + +bool SetVar::evaluate(Rule *rule, Assay *assay) { + std::string targetValue; + + int value = 0; + try { + std::string *resolvedValue = + assay->resolve_variable_first(collectionName, variableName); + if (resolvedValue == NULL) { + value = 0; + } else { + value = stoi(*resolvedValue); + } + } catch (...) { + value = 0; + } + + int pre = 0; + try { + pre = stoi(predicate); + } catch (...) { + /* perform a macro expansion. */ + pre = 0; + } + + switch (operation) { + case setOperation: + /* perform a macro expansion. */ + targetValue = predicate; + break; + case sumAndSetOperation: + targetValue = std::to_string(value + pre); + break; + case substractAndSetOperation: + targetValue = std::to_string(value - pre); + break; + case setToOne: + targetValue = std::string("1"); + break; + } + + assay->setCollection(collectionName, variableName, targetValue); + + return true; +} + +} // namespace actions +} // namespace ModSecurity diff --git a/src/actions/set_var.h b/src/actions/set_var.h new file mode 100644 index 00000000..3f0d46c4 --- /dev/null +++ b/src/actions/set_var.h @@ -0,0 +1,60 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include + +#include "actions/action.h" + +#ifndef SRC_ACTIONS_SET_VAR_H_ +#define SRC_ACTIONS_SET_VAR_H_ + +namespace ModSecurity { +class Assay; +class Rule; + +namespace actions { + + +class SetVar : public Action { + public: + explicit SetVar(std::string action); + + bool evaluate(Rule *rule, Assay *assay) override; + void dump(); + bool init(std::string *error); + + std::string collectionName; + std::string variableName; + std::string predicate; + + enum SetVarOperation { + /* Set variable to something */ + setOperation, + /* read variable, sum predicate and set */ + sumAndSetOperation, + /* read variable, substract predicate and set */ + substractAndSetOperation, + /* set variable to 1 */ + setToOne + }; + + SetVarOperation operation; +}; + +} // namespace actions +} // namespace ModSecurity + + +#endif // SRC_ACTIONS_SET_VAR_H_ diff --git a/src/assay.cc b/src/assay.cc index c6c852ae..347a08bb 100644 --- a/src/assay.cc +++ b/src/assay.cc @@ -124,6 +124,7 @@ Assay::Assay(ModSecurity *ms, Rules *rules) this->m_responseHeadersNames = resolve_variable_first( "RESPONSE_HEADERS_NAMES"); + collections.emplace("TX", new ModSecurityStringVariables()); this->debug(4, "Initialising transaction"); } @@ -135,6 +136,10 @@ Assay::~Assay() { m_requestBody.str(std::string()); m_requestBody.clear(); + for (auto &a : collections) { + delete a.second; + } + m_rules->decrementReferenceCount(); } @@ -1305,7 +1310,7 @@ std::list> } if (l.size() == 0) { - for (auto& x : m_variables_strings) { + for (auto &x : m_variables_strings) { if ((x.first.substr(0, var.size() + 1).compare(var + ":") != 0) && (x.first != var)) { continue; @@ -1320,6 +1325,31 @@ std::list> } } + for (auto &a : collections) { + auto range = a.second->equal_range(var); + + for (auto it = range.first; it != range.second; ++it) { + pair = std::make_pair(std::string(var), std::string(it->second)); + l.push_back(pair); + } + + if (l.size() == 0) { + for (auto &x : *a.second) { + if ((x.first.substr(0, var.size() + 1).compare(var + ":") != 0) + && (x.first != var)) { + continue; + } + std::list> t; + t = resolve_variable(x.first); + for (std::pair z : t) { + pair = std::make_pair(std::string(z.first), + std::string(z.second)); + l.push_back(pair); + } + } + } + } + return l; } @@ -1331,10 +1361,46 @@ std::string* Assay::resolve_variable_first(std::string var) { return &it->second; } + for (auto &a : collections) { + auto range = a.second->equal_range(var); + for (auto it = range.first; it != range.second; ++it) { + return &it->second; + } + } return NULL; } +std::string* Assay::resolve_variable_first(const std::string collectionName, + std::string var) { + for (auto &a : collections) { + if (a.first == collectionName) { + auto range = a.second->equal_range(collectionName + ":" + var); + for (auto it = range.first; it != range.second; ++it) { + return &it->second; + } + } + } + return NULL; +} + + +void Assay::setCollection(const std::string& collectionName, + const std::string& variableName, + const std::string& targetValue) { + ModSecurityStringVariables *collection; + + try { + collection = collections.at(collectionName); + collection->storeOrUpdateVariable(collectionName + ":" + + variableName, targetValue); + } catch (...) { + debug(9, "don't know any collection named: " + + collectionName + ". it was created?"); + return; + } +} + /** * @name msc_new_assay * @brief Create a new assay for a given configuration and ModSecurity core. diff --git a/src/macro_expansion.cc b/src/macro_expansion.cc new file mode 100644 index 00000000..2e0222c8 --- /dev/null +++ b/src/macro_expansion.cc @@ -0,0 +1,23 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include "src/macro_expansion.h" + +namespace ModSecurity { + +MacroExpansion::MacroExpansion() { +} + +} // namespace ModSecurity diff --git a/src/macro_expansion.h b/src/macro_expansion.h new file mode 100644 index 00000000..1573d46e --- /dev/null +++ b/src/macro_expansion.h @@ -0,0 +1,39 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include +#include +#include +#include + +#include "modsecurity/modsecurity.h" + +#ifndef SRC_MACRO_EXPANSION_H_ +#define SRC_MACRO_EXPANSION_H_ + +namespace ModSecurity { + + +class MacroExpansion { + public: + MacroExpansion(); +}; + + +} // namespace ModSecurity + + + +#endif // SRC_MACRO_EXPANSION_H_ diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index 45cd9f99..955bbec8 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -17,6 +17,7 @@ class Driver; } #include "actions/action.h" +#include "actions/set_var.h" #include "actions/transformations/transformation.h" #include "operators/operator.h" #include "rule.h" @@ -40,6 +41,7 @@ class Driver; #include "variables/time_year.h" using ModSecurity::actions::Action; +using ModSecurity::actions::SetVar; using ModSecurity::actions::transformations::Transformation; using ModSecurity::operators::Operator; using ModSecurity::Rule; @@ -62,6 +64,7 @@ using ModSecurity::Variables::TimeWDay; using ModSecurity::Variables::TimeYear; using ModSecurity::Variables::Variable; + #define CHECK_VARIATION_DECL \ Variable *var = NULL; \ bool t = false; @@ -182,6 +185,7 @@ using ModSecurity::Variables::Variable; %token OPERATOR %token ACTION %token ACTION_SEVERITY +%token ACTION_SETVAR %token TRANSFORMATION %token CONFIG_VALUE_NUMBER @@ -596,6 +600,49 @@ actions: actions->push_back(Action::instantiate($1)); $$ = actions; } + | actions COMMA ACTION_SETVAR + { + std::vector *a = $1; + std::string error; + SetVar *setVar = new SetVar($3); + + if (setVar->init(&error) == false) { + driver.parserError << error; + YYERROR; + } + + a->push_back(setVar); + $$ = $1; + } + | SPACE ACTION_SETVAR + { + std::vector *actions = new std::vector; + std::string error; + SetVar *setVar = new SetVar($2); + + if (setVar->init(&error) == false) { + driver.parserError << error; + YYERROR; + } + + actions->push_back(setVar); + $$ = actions; + + } + | ACTION_SETVAR + { + std::vector *actions = new std::vector; + std::string error; + SetVar *setVar = new SetVar($1); + + if (setVar->init(&error) == false) { + driver.parserError << error; + YYERROR; + } + + actions->push_back(setVar); + $$ = actions; + } %% diff --git a/src/parser/seclang-scanner.ll b/src/parser/seclang-scanner.ll index a0e94feb..870908a0 100755 --- a/src/parser/seclang-scanner.ll +++ b/src/parser/seclang-scanner.ll @@ -23,8 +23,9 @@ using ModSecurity::split; %} %option noyywrap nounput batch debug noinput -ACTION (?i:accuracy|allow|append|auditlog|block|capture|chain|ctl|deny|deprecatevar|drop|exec|expirevar|id:[0-9]+|id:'[0-9]+'|initcol|log|logdata|maturity|msg|multiMatch|noauditlog|nolog|pass|pause|phase:[0-9]+|prepend|proxy|redirect:[A-Z0-9_\|\&\:\/\/\.]+|rev|sanitiseArg|sanitiseMatched|sanitiseMatchedBytes|sanitiseRequestHeader|sanitiseResponseHeader|setuid|setrsc|setsid|setenv|setvar|skip|skipAfter|status:[0-9]+|tag|ver|xmlns) +ACTION (?i:accuracy|allow|append|auditlog|block|capture|chain|ctl|deny|deprecatevar|drop|exec|expirevar|id:[0-9]+|id:'[0-9]+'|initcol|log|logdata|maturity|msg|multiMatch|noauditlog|nolog|pass|pause|phase:[0-9]+|prepend|proxy|redirect:[A-Z0-9_\|\&\:\/\/\.]+|rev|sanitiseArg|sanitiseMatched|sanitiseMatchedBytes|sanitiseRequestHeader|sanitiseResponseHeader|setuid|setrsc|setsid|setenv|skip|skipAfter|status:[0-9]+|tag|ver|xmlns) ACTION_SEVERITY (?i:severity:[0-9]+|severity:'[0-9]+'|severity:(EMERGENCY|ALERT|CRITICAL|ERROR|WARNING|NOTICE|INFO|DEBUG)|severity:'(EMERGENCY|ALERT|CRITICAL|ERROR|WARNING|NOTICE|INFO|DEBUG)') +ACTION_SETVAR (?i:setvar) DIRECTIVE SecRule CONFIG_DIRECTIVE SecRequestBodyNoFilesLimit|SecRequestBodyInMemoryLimit|SecPcreMatchLimitRecursion|SecPcreMatchLimit|SecResponseBodyMimeType|SecTmpDir|SecDataDir|SecArgumentSeparator|SecCookieFormat|SecStatusEngine @@ -188,6 +189,15 @@ FREE_TEXT_NEW_LINE [^\"|\n]+ ["]{OPERATORNOARG}["] { return yy::seclang_parser::make_OPERATOR(yytext, *driver.loc.back()); } {ACTION} { return yy::seclang_parser::make_ACTION(yytext, *driver.loc.back()); } {ACTION_SEVERITY} { return yy::seclang_parser::make_ACTION_SEVERITY(yytext, *driver.loc.back()); } +{ACTION_SETVAR}:{FREE_TEXT}={FREE_TEXT} { + return yy::seclang_parser::make_ACTION_SETVAR(strchr(yytext, ':') + 1, *driver.loc.back()); + } +{ACTION_SETVAR}:{FREE_TEXT}=+{FREE_TEXT} { + return yy::seclang_parser::make_ACTION_SETVAR(strchr(yytext, ':') + 1, *driver.loc.back()); + } +{ACTION_SETVAR}:{FREE_TEXT} { + return yy::seclang_parser::make_ACTION_SETVAR(strchr(yytext, ':') + 1, *driver.loc.back()); + } ["] { return yy::seclang_parser::make_QUOTATION_MARK(*driver.loc.back()); } [,] { return yy::seclang_parser::make_COMMA(*driver.loc.back()); } [|] { return yy::seclang_parser::make_PIPE(*driver.loc.back()); } diff --git a/test/test-cases/regression/collection-tx.json b/test/test-cases/regression/collection-tx.json new file mode 100644 index 00000000..83e977a1 --- /dev/null +++ b/test/test-cases/regression/collection-tx.json @@ -0,0 +1,245 @@ +[ + { + "enabled":1, + "version_min":300000, + "version_max":0, + "title":"Testing collection :: TX (1/4)", + "client":{ + "ip":"200.249.12.31", + "port":2313 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "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", + "Cookie":"PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120", + "Pragma":"no-cache", + "Cache-Control":"no-cache" + }, + "uri":"\/test.pl?param1= test ¶m2=test2", + "protocol":"GET", + "http_version":1.1, + "body":"" + }, + "response":{ + "headers":{ + "Content-Type":"text\/xml; charset=utf-8\n\r", + "Content-Length":"length\n\r" + }, + "body":[ + "\n\r", + "\n\r", + " \n\r", + " \n\r", + " string<\/EnlightenResult>\n\r", + " <\/EnlightenResponse>\n\r", + " <\/soap:Body>\n\r", + "<\/soap:Envelope>\n\r" + ] + }, + "expected":{ + "audit_log":"", + "debug_log":"Target value: \"to_test\" \\(Variable: TX:something\\)", + "error_log":"" + }, + "rules":[ + "SecRuleEngine On", + "SecDebugLog \/tmp\/modsec_debug.log", + "SecDebugLogLevel 9", + "SecRule REQUEST_HEADERS \"@contains PHPSESSID\" \"t:lowercase,t:none,setvar:TX.something=to_test\"", + "SecRule TX \"@contains to_test\" \"t:lowercase,t:none\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "version_max":0, + "title":"Testing collection :: TX (2/4)", + "client":{ + "ip":"200.249.12.31", + "port":2313 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "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", + "Cookie":"PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120", + "Pragma":"no-cache", + "Cache-Control":"no-cache" + }, + "uri":"\/test.pl?param1= test ¶m2=test2", + "protocol":"GET", + "http_version":1.1, + "body":"" + }, + "response":{ + "headers":{ + "Content-Type":"text\/xml; charset=utf-8\n\r", + "Content-Length":"length\n\r" + }, + "body":[ + "\n\r", + "\n\r", + " \n\r", + " \n\r", + " string<\/EnlightenResult>\n\r", + " <\/EnlightenResponse>\n\r", + " <\/soap:Body>\n\r", + "<\/soap:Envelope>\n\r" + ] + }, + "expected":{ + "audit_log":"", + "debug_log":"Target value: \"1\" \\(Variable: TX:something\\)", + "error_log":"" + }, + "rules":[ + "SecRuleEngine On", + "SecDebugLog \/tmp\/modsec_debug.log", + "SecDebugLogLevel 9", + "SecRule REQUEST_HEADERS \"@contains PHPSESSID\" \"t:lowercase,t:none,setvar:TX.something\"", + "SecRule TX \"@contains to_test\" \"t:lowercase,t:none\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "version_max":0, + "title":"Testing collection :: TX (3/4)", + "client":{ + "ip":"200.249.12.31", + "port":2313 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "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", + "Cookie":"PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120", + "Pragma":"no-cache", + "Cache-Control":"no-cache" + }, + "uri":"\/test.pl?param1= test ¶m2=test2", + "protocol":"GET", + "http_version":1.1, + "body":"" + }, + "response":{ + "headers":{ + "Content-Type":"text\/xml; charset=utf-8\n\r", + "Content-Length":"length\n\r" + }, + "body":[ + "\n\r", + "\n\r", + " \n\r", + " \n\r", + " string<\/EnlightenResult>\n\r", + " <\/EnlightenResponse>\n\r", + " <\/soap:Body>\n\r", + "<\/soap:Envelope>\n\r" + ] + }, + "expected":{ + "audit_log":"", + "debug_log":"Target value: \"20\" \\(Variable: TX:something\\)", + "error_log":"" + }, + "rules":[ + "SecRuleEngine On", + "SecDebugLog \/tmp\/modsec_debug.log", + "SecDebugLogLevel 9", + "SecRule REQUEST_HEADERS \"@contains PHPSESSID\" \"t:lowercase,t:none,setvar:TX.something=+10\"", + "SecRule REQUEST_HEADERS \"@contains PHPSESSID\" \"t:lowercase,t:none,setvar:TX.something=+10\"", + "SecRule TX \"@contains to_test\" \"t:lowercase,t:none\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "version_max":0, + "title":"Testing collection :: TX (4/4)", + "client":{ + "ip":"200.249.12.31", + "port":2313 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "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", + "Cookie":"PHPSESSID=rAAAAAAA2t5uvjq435r4q7ib3vtdjq120", + "Pragma":"no-cache", + "Cache-Control":"no-cache" + }, + "uri":"\/test.pl?param1= test ¶m2=test2", + "protocol":"GET", + "http_version":1.1, + "body":"" + }, + "response":{ + "headers":{ + "Content-Type":"text\/xml; charset=utf-8\n\r", + "Content-Length":"length\n\r" + }, + "body":[ + "\n\r", + "\n\r", + " \n\r", + " \n\r", + " string<\/EnlightenResult>\n\r", + " <\/EnlightenResponse>\n\r", + " <\/soap:Body>\n\r", + "<\/soap:Envelope>\n\r" + ] + }, + "expected":{ + "audit_log":"", + "debug_log":"Target value: \"15\" \\(Variable: TX:something\\)", + "error_log":"" + }, + "rules":[ + "SecRuleEngine On", + "SecDebugLog \/tmp\/modsec_debug.log", + "SecDebugLogLevel 9", + "SecRule REQUEST_HEADERS \"@contains PHPSESSID\" \"t:lowercase,t:none,setvar:TX.something=+10\"", + "SecRule REQUEST_HEADERS \"@contains PHPSESSID\" \"t:lowercase,t:none,setvar:TX.something=+10\"", + "SecRule REQUEST_HEADERS \"@contains PHPSESSID\" \"t:lowercase,t:none,setvar:TX.something=-5\"", + "SecRule TX \"@contains to_test\" \"t:lowercase,t:none\"" + ] + } +] \ No newline at end of file