Add ctl:auditengine action support

This commit is contained in:
Martin Vierula 2022-01-19 14:06:01 -08:00
parent cb80837e6a
commit 2d51efae49
15 changed files with 4968 additions and 4759 deletions

View File

@ -96,6 +96,7 @@ TESTS+=test/test-cases/regression/action-ctl_request_body_access.json
TESTS+=test/test-cases/regression/action-ctl_request_body_processor.json TESTS+=test/test-cases/regression/action-ctl_request_body_processor.json
TESTS+=test/test-cases/regression/action-ctl_request_body_processor_urlencoded.json TESTS+=test/test-cases/regression/action-ctl_request_body_processor_urlencoded.json
TESTS+=test/test-cases/regression/action-ctl_rule_engine.json TESTS+=test/test-cases/regression/action-ctl_rule_engine.json
TESTS+=test/test-cases/regression/action-ctl_audit_engine.json
TESTS+=test/test-cases/regression/action-ctl_rule_remove_by_id.json TESTS+=test/test-cases/regression/action-ctl_rule_remove_by_id.json
TESTS+=test/test-cases/regression/action-ctl_rule_remove_by_tag.json TESTS+=test/test-cases/regression/action-ctl_rule_remove_by_tag.json
TESTS+=test/test-cases/regression/action-ctl_rule_remove_target_by_id.json TESTS+=test/test-cases/regression/action-ctl_rule_remove_target_by_id.json

View File

@ -22,12 +22,11 @@
#ifndef HEADERS_MODSECURITY_AUDIT_LOG_H_ #ifndef HEADERS_MODSECURITY_AUDIT_LOG_H_
#define HEADERS_MODSECURITY_AUDIT_LOG_H_ #define HEADERS_MODSECURITY_AUDIT_LOG_H_
#include "modsecurity/transaction.h"
#ifdef __cplusplus #ifdef __cplusplus
namespace modsecurity { namespace modsecurity {
class Transaction;
namespace audit_log { namespace audit_log {
namespace writer { namespace writer {
class Writer; class Writer;
@ -177,6 +176,10 @@ class AuditLog {
static int addParts(int parts, const std::string& new_parts); static int addParts(int parts, const std::string& new_parts);
static int removeParts(int parts, const std::string& new_parts); static int removeParts(int parts, const std::string& new_parts);
void setCtlAuditEngineActive() {
m_ctlAuditEngineActive = true;
}
bool merge(AuditLog *from, std::string *error); bool merge(AuditLog *from, std::string *error);
std::string m_path1; std::string m_path1;
@ -203,6 +206,7 @@ class AuditLog {
std::string m_relevant; std::string m_relevant;
audit_log::writer::Writer *m_writer; audit_log::writer::Writer *m_writer;
bool m_ctlAuditEngineActive; // rules have at least one action On or RelevantOnly
}; };

View File

@ -49,6 +49,7 @@ typedef struct Rules_t RulesSet;
#include "modsecurity/collection/collection.h" #include "modsecurity/collection/collection.h"
#include "modsecurity/variable_origin.h" #include "modsecurity/variable_origin.h"
#include "modsecurity/anchored_set_variable_translation_proxy.h" #include "modsecurity/anchored_set_variable_translation_proxy.h"
#include "modsecurity/audit_log.h"
#ifndef NO_LOGS #ifndef NO_LOGS
@ -529,6 +530,12 @@ class Transaction : public TransactionAnchoredVariables, public TransactionSecMa
*/ */
std::list< std::pair<int, std::string> > m_auditLogModifier; std::list< std::pair<int, std::string> > m_auditLogModifier;
/**
* This transaction's most recent action ctl:auditEngine
*
*/
audit_log::AuditLog::AuditLogStatus m_ctlAuditEngine;
/** /**
* This variable holds all the messages asked to be save by the utilization * This variable holds all the messages asked to be save by the utilization
* of the actions: `log_data' and `msg'. These should be included on the * of the actions: `log_data' and `msg'. These should be included on the

View File

@ -118,6 +118,7 @@ ACTIONS = \
actions/capture.cc \ actions/capture.cc \
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/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 \

View File

@ -0,0 +1,63 @@
/*
* ModSecurity, http://www.modsecurity.org/
* Copyright (c) 2022 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* If any of the files related to licensing are missing or if you have any
* other questions related to licensing please contact Trustwave Holdings, Inc.
* directly using the email address security@modsecurity.org.
*
*/
#include "src/actions/ctl/audit_engine.h"
#include <string>
#include "modsecurity/rules_set_properties.h"
#include "modsecurity/rules_set.h"
#include "modsecurity/transaction.h"
namespace modsecurity {
namespace actions {
namespace ctl {
bool AuditEngine::init(std::string *error) {
std::string what(m_parser_payload, 12, m_parser_payload.size() - 12);
if (what == "on") {
m_auditEngine = audit_log::AuditLog::AuditLogStatus::OnAuditLogStatus;
} else if (what == "off") {
m_auditEngine = audit_log::AuditLog::AuditLogStatus::OffAuditLogStatus;
} else if (what == "relevantonly") {
m_auditEngine = audit_log::AuditLog::AuditLogStatus::RelevantOnlyAuditLogStatus;
} else {
error->assign("Internal error. Expected: On, Off or RelevantOnly; " \
"got: " + m_parser_payload);
return false;
}
return true;
}
bool AuditEngine::evaluate(RuleWithActions *rule, Transaction *transaction) {
std::stringstream a;
a << "Setting SecAuditEngine to ";
a << std::to_string(m_auditEngine);
a << " as requested by a ctl:auditEngine action";
ms_dbg_a(transaction, 8, a.str());
transaction->m_ctlAuditEngine = m_auditEngine;
return true;
}
} // namespace ctl
} // namespace actions
} // namespace modsecurity

View File

@ -0,0 +1,51 @@
/*
* ModSecurity, http://www.modsecurity.org/
* Copyright (c) 2022 Trustwave Holdings, Inc. (http://www.trustwave.com/)
*
* You may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* If any of the files related to licensing are missing or if you have any
* other questions related to licensing please contact Trustwave Holdings, Inc.
* directly using the email address security@modsecurity.org.
*
*/
#include <string>
#include "modsecurity/rules_set_properties.h"
#include "modsecurity/actions/action.h"
#include "modsecurity/audit_log.h"
#ifndef SRC_ACTIONS_CTL_AUDIT_ENGINE_H_
#define SRC_ACTIONS_CTL_AUDIT_ENGINE_H_
namespace modsecurity {
class Transaction;
namespace actions {
namespace ctl {
class AuditEngine : public Action {
public:
explicit AuditEngine(const std::string &action)
: Action(action, RunTimeOnlyIfMatchKind),
m_auditEngine(audit_log::AuditLog::AuditLogStatus::NotSetLogStatus) { }
bool init(std::string *error) override;
bool evaluate(RuleWithActions *rule, Transaction *transaction) override;
audit_log::AuditLog::AuditLogStatus m_auditEngine;
};
} // namespace ctl
} // namespace actions
} // namespace modsecurity
#endif // SRC_ACTIONS_CTL_AUDIT_ENGINE_H_

View File

@ -21,6 +21,7 @@
#include <fstream> #include <fstream>
#include "modsecurity/transaction.h"
#include "modsecurity/rule_message.h" #include "modsecurity/rule_message.h"
#include "src/audit_log/writer/https.h" #include "src/audit_log/writer/https.h"
#include "src/audit_log/writer/parallel.h" #include "src/audit_log/writer/parallel.h"
@ -61,7 +62,8 @@ AuditLog::AuditLog()
m_status(NotSetLogStatus), m_status(NotSetLogStatus),
m_type(NotSetAuditLogType), m_type(NotSetAuditLogType),
m_relevant(""), m_relevant(""),
m_writer(NULL) { } m_writer(NULL),
m_ctlAuditEngineActive(false) { }
AuditLog::~AuditLog() { AuditLog::~AuditLog() {
@ -210,7 +212,8 @@ bool AuditLog::setType(AuditLogType audit_type) {
bool AuditLog::init(std::string *error) { bool AuditLog::init(std::string *error) {
audit_log::writer::Writer *tmp_writer; audit_log::writer::Writer *tmp_writer;
if (m_status == OffAuditLogStatus || m_status == NotSetLogStatus) { if ((m_status == OffAuditLogStatus || m_status == NotSetLogStatus)
&& !m_ctlAuditEngineActive) {
if (m_writer) { if (m_writer) {
delete m_writer; delete m_writer;
m_writer = NULL; m_writer = NULL;
@ -275,7 +278,13 @@ bool AuditLog::saveIfRelevant(Transaction *transaction) {
bool AuditLog::saveIfRelevant(Transaction *transaction, int parts) { bool AuditLog::saveIfRelevant(Transaction *transaction, int parts) {
bool saveAnyway = false; bool saveAnyway = false;
if (m_status == OffAuditLogStatus || m_status == NotSetLogStatus) {
AuditLogStatus transactionAuditLogStatus(m_status);
if (transaction->m_ctlAuditEngine != NotSetLogStatus) {
transactionAuditLogStatus = transaction->m_ctlAuditEngine;
}
if (transactionAuditLogStatus == OffAuditLogStatus || transactionAuditLogStatus == NotSetLogStatus) {
ms_dbg_a(transaction, 5, "Audit log engine was not set."); ms_dbg_a(transaction, 5, "Audit log engine was not set.");
return true; return true;
} }
@ -287,7 +296,7 @@ bool AuditLog::saveIfRelevant(Transaction *transaction, int parts) {
} }
} }
if ((m_status == RelevantOnlyAuditLogStatus if ((transactionAuditLogStatus == RelevantOnlyAuditLogStatus
&& this->isRelevant(transaction->m_httpCodeReturned) == false) && this->isRelevant(transaction->m_httpCodeReturned) == false)
&& saveAnyway == false) { && saveAnyway == false) {
ms_dbg_a(transaction, 9, "Return code `" + ms_dbg_a(transaction, 9, "Return code `" +
@ -353,6 +362,10 @@ bool AuditLog::merge(AuditLog *from, std::string *error) {
m_format = from->m_format; m_format = from->m_format;
} }
if (from->m_ctlAuditEngineActive) {
m_ctlAuditEngineActive = from->m_ctlAuditEngineActive;
}
return init(error); return init(error);
} }

File diff suppressed because it is too large Load Diff

View File

@ -64,6 +64,7 @@ class Driver;
#include "src/actions/block.h" #include "src/actions/block.h"
#include "src/actions/capture.h" #include "src/actions/capture.h"
#include "src/actions/chain.h" #include "src/actions/chain.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/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"
@ -350,7 +351,7 @@ using namespace modsecurity::operators;
a = std::move(c); a = std::move(c);
#line 354 "seclang-parser.hh" #line 355 "seclang-parser.hh"
# include <cassert> # include <cassert>
# include <cstdlib> // std::abort # include <cstdlib> // std::abort
@ -484,7 +485,7 @@ using namespace modsecurity::operators;
#endif #endif
namespace yy { namespace yy {
#line 488 "seclang-parser.hh" #line 489 "seclang-parser.hh"
@ -8625,7 +8626,7 @@ switch (yykind)
} }
} // yy } // yy
#line 8629 "seclang-parser.hh" #line 8630 "seclang-parser.hh"

View File

@ -25,6 +25,7 @@ class Driver;
#include "src/actions/block.h" #include "src/actions/block.h"
#include "src/actions/capture.h" #include "src/actions/capture.h"
#include "src/actions/chain.h" #include "src/actions/chain.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/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"
@ -2625,18 +2626,17 @@ act:
} }
| ACTION_CTL_AUDIT_ENGINE CONFIG_VALUE_ON | ACTION_CTL_AUDIT_ENGINE CONFIG_VALUE_ON
{ {
//ACTION_NOT_SUPPORTED("CtlAuditEngine", @0); ACTION_CONTAINER($$, new actions::ctl::AuditEngine("ctl:auditengine=on"));
ACTION_CONTAINER($$, new actions::Action($1)); driver.m_auditLog->setCtlAuditEngineActive();
} }
| ACTION_CTL_AUDIT_ENGINE CONFIG_VALUE_OFF | ACTION_CTL_AUDIT_ENGINE CONFIG_VALUE_OFF
{ {
//ACTION_NOT_SUPPORTED("CtlAuditEngine", @0); ACTION_CONTAINER($$, new actions::ctl::AuditEngine("ctl:auditengine=off"));
ACTION_CONTAINER($$, new actions::Action($1));
} }
| ACTION_CTL_AUDIT_ENGINE CONFIG_VALUE_RELEVANT_ONLY | ACTION_CTL_AUDIT_ENGINE CONFIG_VALUE_RELEVANT_ONLY
{ {
//ACTION_NOT_SUPPORTED("CtlAuditEngine", @0); ACTION_CONTAINER($$, new actions::ctl::AuditEngine("ctl:auditengine=relevantonly"));
ACTION_CONTAINER($$, new actions::Action($1)); driver.m_auditLog->setCtlAuditEngineActive();
} }
| ACTION_CTL_AUDIT_LOG_PARTS | ACTION_CTL_AUDIT_LOG_PARTS
{ {

File diff suppressed because it is too large Load Diff

View File

@ -613,6 +613,7 @@ EQUALS_MINUS (?i:=\-)
{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_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()); }
[ \t]*\\\n[ \t]* { driver.loc.back()->lines(1); driver.loc.back()->step(); } [ \t]*\\\n[ \t]* { driver.loc.back()->lines(1); driver.loc.back()->step(); }
[ \t]*\\\r\n[ \t]* { driver.loc.back()->lines(1); driver.loc.back()->step(); } [ \t]*\\\r\n[ \t]* { driver.loc.back()->lines(1); driver.loc.back()->step(); }
} }

View File

@ -122,6 +122,7 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, void *logCbData)
m_ruleRemoveTargetById(), m_ruleRemoveTargetById(),
m_requestBodyAccess(RulesSet::PropertyNotSetConfigBoolean), m_requestBodyAccess(RulesSet::PropertyNotSetConfigBoolean),
m_auditLogModifier(), m_auditLogModifier(),
m_ctlAuditEngine(AuditLog::AuditLogStatus::NotSetLogStatus),
m_rulesMessages(), m_rulesMessages(),
m_requestBody(), m_requestBody(),
m_responseBody(), m_responseBody(),
@ -195,6 +196,7 @@ Transaction::Transaction(ModSecurity *ms, RulesSet *rules, char *id, void *logCb
m_ruleRemoveTargetById(), m_ruleRemoveTargetById(),
m_requestBodyAccess(RulesSet::PropertyNotSetConfigBoolean), m_requestBodyAccess(RulesSet::PropertyNotSetConfigBoolean),
m_auditLogModifier(), m_auditLogModifier(),
m_ctlAuditEngine(AuditLog::AuditLogStatus::NotSetLogStatus),
m_rulesMessages(), m_rulesMessages(),
m_requestBody(), m_requestBody(),
m_responseBody(), m_responseBody(),

View File

@ -35,8 +35,8 @@ invalidScanfArgType_int:src/rules_set_properties.cc:102
unmatchedSuppression:src/utils/geo_lookup.cc:82 unmatchedSuppression:src/utils/geo_lookup.cc:82
useInitializationList:src/utils/shared_files.h:87 useInitializationList:src/utils/shared_files.h:87
unmatchedSuppression:src/utils/msc_tree.cc unmatchedSuppression:src/utils/msc_tree.cc
functionStatic:headers/modsecurity/transaction.h:407 functionStatic:headers/modsecurity/transaction.h:408
duplicateBranch:src/audit_log/audit_log.cc:223 duplicateBranch:src/audit_log/audit_log.cc:226
unreadVariable:src/request_body_processor/multipart.cc:435 unreadVariable:src/request_body_processor/multipart.cc:435
stlcstrParam:src/audit_log/writer/parallel.cc:145 stlcstrParam:src/audit_log/writer/parallel.cc:145
functionStatic:src/engine/lua.h:70 functionStatic:src/engine/lua.h:70
@ -54,7 +54,7 @@ duplicateBranch:src/request_body_processor/multipart.cc:93
danglingTempReference:src/modsecurity.cc:206 danglingTempReference:src/modsecurity.cc:206
knownConditionTrueFalse:src/operators/validate_url_encoding.cc:77 knownConditionTrueFalse:src/operators/validate_url_encoding.cc:77
knownConditionTrueFalse:src/operators/verify_svnr.cc:87 knownConditionTrueFalse:src/operators/verify_svnr.cc:87
rethrowNoCurrentException:headers/modsecurity/transaction.h:306 rethrowNoCurrentException:headers/modsecurity/transaction.h:307
rethrowNoCurrentException:src/rule_with_actions.cc:123 rethrowNoCurrentException:src/rule_with_actions.cc:123
noExplicitConstructor:seclang-parser.hh noExplicitConstructor:seclang-parser.hh

View File

@ -0,0 +1,51 @@
[
{
"enabled": 1,
"version_min": 300000,
"version_max": 0,
"title": "auditengine : Config=Off, ctl:auditEngine=on",
"client": {
"ip": "200.249.12.31",
"port": 2313
},
"server": {
"ip": "200.249.12.31",
"port": 80
},
"request": {
"headers": {
"Host": "www.modsecurity.org",
"User-Agent": "Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko\/20091102 Firefox\/3.5.5 (.NET CLR 3.5.30729)",
"Accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8",
"Accept-Language": "en-us,en;q=0.5",
"Accept-Encoding": "gzip,deflate",
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
"Keep-Alive": "300",
"Connection": "keep-alive",
"Pragma": "no-cache",
"Cache-Control": "no-cache"
},
"uri": "\/test.pl?parm1=test1&parm2=test2",
"method": "GET",
"http_version": 1.1,
"body": ""
},
"expected": {
"audit_log": "--A--",
"error_log": "",
"http_code": 200
},
"rules": [
"SecRuleEngine On",
"SecDefaultAction \"phase:2,nolog,pass\"",
"SecAuditEngine Off",
"SecAuditLogParts ABCFHZ",
"SecAuditLog /tmp/modsec_test_ctl_auditengine_auditlog_1.log",
"SecAuditLogDirMode 0766",
"SecAuditLogFileMode 0666",
"SecAuditLogType Serial",
"SecAuditLogRelevantStatus \"^(?:5|4(?!04))\"",
"SecRule ARGS \"@contains test2\" \"id:1701,phase:2,pass,nolog,ctl:auditEngine=on\""
]
}
]