From f519717bdfdacba27ddc050c25cb58a518bf213d Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Fri, 7 Aug 2015 01:48:16 -0300 Subject: [PATCH] Adds support to the msg action --- headers/modsecurity/assay.h | 3 ++ src/Makefile.am | 1 + src/actions/msg.cc | 46 ++++++++++++++++ src/actions/msg.h | 44 +++++++++++++++ src/assay.cc | 3 ++ src/parser/seclang-parser.yy | 24 +++++++++ src/parser/seclang-scanner.ll | 7 ++- test/test-cases/regression/action-msg.json | 62 ++++++++++++++++++++++ 8 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 src/actions/msg.cc create mode 100644 src/actions/msg.h create mode 100644 test/test-cases/regression/action-msg.json diff --git a/headers/modsecurity/assay.h b/headers/modsecurity/assay.h index 642b998e..66bd3130 100644 --- a/headers/modsecurity/assay.h +++ b/headers/modsecurity/assay.h @@ -239,6 +239,7 @@ class Assay { std::unordered_map collections; void debug(int, std::string); + void serverLog(const std::string& msg); std::vector actions; bool save_in_auditlog; @@ -258,6 +259,8 @@ class Assay { Rules *m_rules; + std::list rulesMessages; + private: std::ofstream myfile; ModSecurity *m_ms; diff --git a/src/Makefile.am b/src/Makefile.am index 4c7b7998..9c7e7433 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -56,6 +56,7 @@ ACTIONS = \ actions/block.cc \ actions/capture.cc \ actions/chain.cc \ + actions/msg.cc \ actions/no_audit_log.cc \ actions/phase.cc \ actions/redirect.cc \ diff --git a/src/actions/msg.cc b/src/actions/msg.cc new file mode 100644 index 00000000..06295379 --- /dev/null +++ b/src/actions/msg.cc @@ -0,0 +1,46 @@ +/* + * 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/msg.h" + +#include +#include + +#include "actions/action.h" +#include "modsecurity/assay.h" +#include "src/utils.h" +#include "src/macro_expansion.h" + +namespace ModSecurity { +namespace actions { + +Msg::Msg(std::string action) + : Action(action, RunTimeOnlyIfMatchKind), + m_msg(action) { + m_msg.erase(0, 1); + m_msg.pop_back(); +} + + +bool Msg::evaluate(Rule *rule, Assay *assay) { + std::string msg = MacroExpansion::expand(m_msg, assay); + assay->debug(9, "Saving msg: " + msg); + assay->rulesMessages.push_back(msg); + assay->serverLog(msg); + return true; +} + +} // namespace actions +} // namespace ModSecurity diff --git a/src/actions/msg.h b/src/actions/msg.h new file mode 100644 index 00000000..3bd2cfa2 --- /dev/null +++ b/src/actions/msg.h @@ -0,0 +1,44 @@ +/* + * 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_MSG_H_ +#define SRC_ACTIONS_MSG_H_ + +class Assay; + +namespace ModSecurity { +class Assay; +namespace actions { + + +class Msg : public Action { + public: + explicit Msg(std::string action); + + bool evaluate(Rule *rule, Assay *assay) override; + + private: + std::string m_msg; +}; + + +} // namespace actions +} // namespace ModSecurity + +#endif // SRC_ACTIONS_MSG_H_ diff --git a/src/assay.cc b/src/assay.cc index 921506d4..5f58c62b 100644 --- a/src/assay.cc +++ b/src/assay.cc @@ -1353,6 +1353,9 @@ std::list> return l; } +void Assay::serverLog(const std::string& msg) { + std::cerr << "Server log is not ready : " << msg << std::endl; +} std::string* Assay::resolve_variable_first(std::string var) { auto range = m_variables_strings.equal_range(var); diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index 955bbec8..9fad406f 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -18,6 +18,7 @@ class Driver; #include "actions/action.h" #include "actions/set_var.h" +#include "actions/msg.h" #include "actions/transformations/transformation.h" #include "operators/operator.h" #include "rule.h" @@ -42,6 +43,7 @@ class Driver; using ModSecurity::actions::Action; using ModSecurity::actions::SetVar; +using ModSecurity::actions::Msg; using ModSecurity::actions::transformations::Transformation; using ModSecurity::operators::Operator; using ModSecurity::Rule; @@ -186,6 +188,7 @@ using ModSecurity::Variables::Variable; %token ACTION %token ACTION_SEVERITY %token ACTION_SETVAR +%token ACTION_MSG %token TRANSFORMATION %token CONFIG_VALUE_NUMBER @@ -643,7 +646,28 @@ actions: actions->push_back(setVar); $$ = actions; } + | actions COMMA ACTION_MSG + { + std::vector *a = $1; + Msg *msg = new Msg($3); + a->push_back(msg); + $$ = $1; + } + | SPACE ACTION_MSG + { + std::vector *actions = new std::vector; + Msg *msg = new Msg($2); + actions->push_back(msg); + $$ = actions; + } + | ACTION_MSG + { + std::vector *actions = new std::vector; + Msg *msg = new Msg($1); + actions->push_back(msg); + $$ = actions; + } %% void diff --git a/src/parser/seclang-scanner.ll b/src/parser/seclang-scanner.ll index 870908a0..6db2e91e 100755 --- a/src/parser/seclang-scanner.ll +++ b/src/parser/seclang-scanner.ll @@ -23,9 +23,10 @@ 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|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|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) +ACTION_MSG (?i:msg) DIRECTIVE SecRule CONFIG_DIRECTIVE SecRequestBodyNoFilesLimit|SecRequestBodyInMemoryLimit|SecPcreMatchLimitRecursion|SecPcreMatchLimit|SecResponseBodyMimeType|SecTmpDir|SecDataDir|SecArgumentSeparator|SecCookieFormat|SecStatusEngine @@ -154,7 +155,7 @@ FREE_TEXT_NEW_LINE [^\"|\n]+ %{ /* Variables: TIME */ %} [!|&]?{RUN_TIME_VAR_TIME} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME(yytext, *driver.loc.back()); } [!|&]?{RUN_TIME_VAR_TIME_DAY} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_DAY(yytext, *driver.loc.back()); } -[!|&]?[&]?{RUN_TIME_VAR_TIME_EPOCH} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_EPOCH(yytext, *driver.loc.back()); } +[!|&]?{RUN_TIME_VAR_TIME_EPOCH} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_EPOCH(yytext, *driver.loc.back()); } [!|&]?{RUN_TIME_VAR_TIME_HOUR} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_HOUR(yytext, *driver.loc.back()); } [!|&]?{RUN_TIME_VAR_TIME_MIN} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_MIN(yytext, *driver.loc.back()); } [!|&]?{RUN_TIME_VAR_TIME_MON} { return yy::seclang_parser::make_RUN_TIME_VAR_TIME_MON(yytext, *driver.loc.back()); } @@ -198,6 +199,8 @@ FREE_TEXT_NEW_LINE [^\"|\n]+ {ACTION_SETVAR}:{FREE_TEXT} { return yy::seclang_parser::make_ACTION_SETVAR(strchr(yytext, ':') + 1, *driver.loc.back()); } +{ACTION_MSG}:'{FREE_TEXT}' { return yy::seclang_parser::make_ACTION_MSG(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/action-msg.json b/test/test-cases/regression/action-msg.json new file mode 100644 index 00000000..c0cc023f --- /dev/null +++ b/test/test-cases/regression/action-msg.json @@ -0,0 +1,62 @@ +[ + { + "enabled":1, + "version_min":300000, + "version_max":0, + "title":"Testing action :: msg (this test is not really testing it)", + "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":"Saving msg: This is a test, text\/html,application", + "error_log":"" + }, + "rules":[ + "SecRuleEngine On", + "SecDebugLog \/tmp\/modsec_debug.log", + "SecDebugLogLevel 9", + "SecRule REQUEST_HEADERS \"@contains PHPSESSID\" \"t:lowercase,t:none,msg:'This is a test, %{REQUEST_HEADERS:Accept}%'\"", + "SecRule TX \"@contains to_test\" \"t:lowercase,t:none\"" + ] + } +] \ No newline at end of file