Adds variable TX and action "capture".

This commit is contained in:
Felipe Zimmerle 2015-08-05 10:07:47 -03:00
parent be4a0cb41c
commit 4f47651a6f
34 changed files with 338 additions and 30 deletions

View File

@ -44,6 +44,7 @@ VARIABLES = \
variables/time_sec.cc \
variables/time_wday.cc \
variables/time_year.cc \
variables/tx.cc \
variables/variable.cc
@ -52,6 +53,7 @@ ACTIONS = \
actions/action.cc \
actions/audit_log.cc \
actions/block.cc \
actions/capture.cc \
actions/chain.cc \
actions/no_audit_log.cc \
actions/phase.cc \

View File

@ -19,6 +19,8 @@
#include <string>
#include "modsecurity/assay.h"
#include "src/rule.h"
#include "actions/block.h"
#include "actions/chain.h"
#include "actions/redirect.h"
@ -26,6 +28,7 @@
#include "actions/rule_id.h"
#include "actions/phase.h"
#include "actions/severity.h"
#include "actions/capture.h"
@ -42,12 +45,7 @@ std::string Action::evaluate(std::string value,
}
bool Action::evaluate(Assay *assay) {
return true;
}
bool Action::evaluate(Rule *rule) {
bool Action::evaluate(Rule *rule, Assay *assay) {
return true;
}
@ -84,6 +82,9 @@ Action *Action::instantiate(const std::string& name) {
if (name == "chain") {
return new Chain(name);
}
if (name == "capture") {
return new Capture(name);
}
return new Action(name);
}

View File

@ -80,8 +80,7 @@ class Action {
virtual std::string evaluate(std::string exp,
Assay *assay);
virtual bool evaluate(Assay *assay);
virtual bool evaluate(Rule *rule);
virtual bool evaluate(Rule *rule, Assay *assay);
static Action *instantiate(const std::string& name);

View File

@ -23,7 +23,7 @@
namespace ModSecurity {
namespace actions {
bool AuditLog::evaluate(Assay *assay) {
bool AuditLog::evaluate(Rule *rule, Assay *assay) {
assay->save_in_auditlog = true;
return true;
}

View File

@ -34,7 +34,7 @@ class AuditLog : public Action {
explicit AuditLog(std::string action)
: Action(action, RunTimeOnlyIfMatchKind) { }
bool evaluate(Assay *assay) override;
bool evaluate(Rule *rule, Assay *assay) override;
};
} // namespace actions

View File

@ -30,7 +30,7 @@ Block::Block(std::string action)
}
bool Block::evaluate(Assay *assay) {
bool Block::evaluate(Rule *rule, Assay *assay) {
assay->actions.push_back(this);
return true;
}

View File

@ -33,7 +33,7 @@ class Block : public Action {
public:
explicit Block(std::string action);
bool evaluate(Assay *assay) override;
bool evaluate(Rule *rule, Assay *assay) override;
void fill_intervention(ModSecurityIntervention *i) override;
};

67
src/actions/capture.cc Normal file
View File

@ -0,0 +1,67 @@
/*
* 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/capture.h"
#include <iostream>
#include <string>
#include <list>
#include "modsecurity/assay.h"
#include "src/rule.h"
#include "operators/operator.h"
#include "operators/pm.h"
#include "operators/rx.h"
namespace ModSecurity {
namespace actions {
bool Capture::evaluate(Rule *rule, Assay *assay) {
operators::Operator *op = rule->op;
std::list<std::string> match;
operators::Pm *pm = dynamic_cast<operators::Pm *>(op);
operators::Rx *rx = dynamic_cast<operators::Rx *>(op);
if (pm != NULL) {
match = pm->matched;
}
if (rx != NULL) {
match = rx->matched;
}
if (match.empty()) {
return false;
}
int i = 0;
while (match.empty() == false) {
std::string varName = "TX:" + std::to_string(i);
std::string *a = assay->resolve_variable_first(varName);
if (a == NULL) {
assay->store_variable(varName, match.back());
} else {
assay->update_variable_first(varName, match.back());
}
match.pop_back();
}
return true;
}
} // namespace actions
} // namespace ModSecurity

41
src/actions/capture.h Normal file
View File

@ -0,0 +1,41 @@
/*
* 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 <string>
#include "actions/action.h"
#ifndef SRC_ACTIONS_CAPTURE_H_
#define SRC_ACTIONS_CAPTURE_H_
namespace ModSecurity {
class Rule;
namespace actions {
class Capture : public Action {
public:
explicit Capture(std::string action)
: Action(action, RunTimeOnlyIfMatchKind) { }
bool evaluate(Rule *rule, Assay *assay) override;
};
} // namespace actions
} // namespace ModSecurity
#endif // SRC_ACTIONS_CAPTURE_H_

View File

@ -26,7 +26,7 @@ namespace actions {
bool Chain::evaluate(Rule *rule) {
bool Chain::evaluate(Rule *rule, Assay *assay) {
rule->chained = true;
return true;
}

View File

@ -35,7 +35,7 @@ class Chain : public Action {
explicit Chain(std::string action)
: Action(action, ConfigurationKind) { }
bool evaluate(Rule *rule) override;
bool evaluate(Rule *rule, Assay *assay) override;
};
} // namespace actions

View File

@ -23,7 +23,7 @@
namespace ModSecurity {
namespace actions {
bool NoAuditLog::evaluate(Assay *assay) {
bool NoAuditLog::evaluate(Rule *rule, Assay *assay) {
assay->do_not_save_in_auditlog = true;
return true;
}

View File

@ -34,7 +34,7 @@ class NoAuditLog : public Action {
explicit NoAuditLog(std::string action)
: Action(action, RunTimeOnlyIfMatchKind) { }
bool evaluate(Assay *assay) override;
bool evaluate(Rule *rule, Assay *assay) override;
};
} // namespace actions

View File

@ -41,7 +41,7 @@ Phase::Phase(std::string action)
}
}
bool Phase::evaluate(Rule *rule) {
bool Phase::evaluate(Rule *rule, Assay *assay) {
rule->phase = this->phase;
return true;
}

View File

@ -34,7 +34,7 @@ class Phase : public Action {
public:
explicit Phase(std::string action);
bool evaluate(Rule *rule) override;
bool evaluate(Rule *rule, Assay *assay) override;
int phase;
};

View File

@ -34,7 +34,7 @@ Redirect::Redirect(const std::string& action)
}
bool Redirect::evaluate(Assay *assay) {
bool Redirect::evaluate(Rule *rule, Assay *assay) {
assay->actions.push_back(this);
return true;
}

View File

@ -33,7 +33,7 @@ class Redirect : public Action {
explicit Redirect(const std::string &action);
~Redirect() override;
bool evaluate(Assay *assay) override;
bool evaluate(Rule *rule, Assay *assay) override;
int status;
std::string url;
void fill_intervention(ModSecurityIntervention *i) override;

View File

@ -37,7 +37,7 @@ RuleId::RuleId(std::string action)
}
bool RuleId::evaluate(Rule *rule) {
bool RuleId::evaluate(Rule *rule, Assay *assay) {
rule->rule_id = this->rule_id;
return true;
}

View File

@ -34,7 +34,7 @@ class RuleId : public Action {
public:
explicit RuleId(std::string action);
bool evaluate(Rule *rule) override;
bool evaluate(Rule *rule, Assay *assay) override;
double rule_id;
};

View File

@ -51,7 +51,7 @@ Severity::Severity(std::string action)
}
bool Severity::evaluate(Assay *assay) {
bool Severity::evaluate(Rule *rule, Assay *assay) {
assay->debug(9, "This rule severity is: " + \
std::to_string(this->m_severity) + " current assay is: " + \
std::to_string(assay->highest_severity));

View File

@ -33,7 +33,7 @@ class Severity : public Action {
public:
explicit Severity(std::string action);
bool evaluate(Assay *assay) override;
bool evaluate(Rule *rule, Assay *assay) override;
private:
int m_severity;

View File

@ -33,7 +33,7 @@ Status::Status(std::string action)
}
bool Status::evaluate(Assay *assay) {
bool Status::evaluate(Rule *rule, Assay *assay) {
assay->actions.push_back(this);
return true;
}

View File

@ -31,7 +31,7 @@ class Status : public Action {
public:
explicit Status(std::string actions);
bool evaluate(Assay *assay) override;
bool evaluate(Rule *rule, Assay *assay) override;
void fill_intervention(ModSecurityIntervention *i) override;
int status;
};

View File

@ -20,6 +20,7 @@
#include <iterator>
#include <sstream>
#include <vector>
#include <list>
#include "operators/operator.h"
#include "utils/acmp.h"
@ -68,7 +69,7 @@ bool Pm::evaluate(Assay *assay, const std::string &input) {
rc = acmp_process_quick(&pt, &match, input.c_str(), input.length());
if (rc == 1) {
// save into tx, etc...
this->matched.push_back(std::string(match));
}
return rc == 1;

View File

@ -17,6 +17,7 @@
#define SRC_OPERATORS_PM_H_
#include <string>
#include <list>
#include "operators/operator.h"
#include "utils/acmp.h"
@ -40,6 +41,7 @@ class Pm : public Operator {
virtual bool init(const char **error);
void postOrderTraversal(acmp_btree_node_t *node);
std::list<std::string> matched;
protected:
ACMP *m_p;
};

View File

@ -16,6 +16,7 @@
#include "operators/rx.h"
#include <string>
#include <list>
#include "operators/operator.h"
@ -27,6 +28,7 @@ bool Rx::evaluate(Assay *assay, const std::string& input) {
SMatch match;
if (regex_search(input, &match, m_re) && match.size() >= 1) {
this->matched.push_back(match.match);
return true;
}

View File

@ -17,6 +17,7 @@
#define SRC_OPERATORS_RX_H_
#include <string>
#include <list>
#include "operators/operator.h"
#include "utils/regex.h"
@ -38,6 +39,8 @@ class Rx : public Operator {
m_re(param) { }
bool evaluate(Assay *assay, const std::string &input);
std::list<std::string> matched;
private:
Regex m_re;
};

View File

@ -62,7 +62,7 @@ CONFIG_SEC_REMOTE_RULES (?i:SecRemoteRules)
CONFIG_SEC_REMOTE_RULES_FAIL_ACTION (?i:SecRemoteRulesFailAction)
DICT_ELEMENT [A-Za-z_]+
DICT_ELEMENT [A-Za-z_0-9]+
OPERATOR (?i:(?:@inspectFile|@fuzzyHash|@validateByteRange|@validateDTD|@validateHash|@validateSchema|@verifyCC|@verifyCPF|@verifySSN|@gsbLookup|@rsub)|(?:\!{0,1})(?:@within|@containsWord|@contains|@endsWith|@eq|@ge|@gt|@ipMatchF|@ipMatch|@ipMatchFromFile|@le|@lt|@pmf|@pm|@pmFromFile|@rbl|@rx|@streq|@strmatch|@beginsWith))

View File

@ -74,7 +74,7 @@ Rule::Rule(Operator *_op,
for (Action *a : *actions) {
if (a->action_kind == Action::ConfigurationKind) {
actions_conf.push_back(a);
a->evaluate(this);
a->evaluate(this, NULL);
} else if (a->action_kind == Action::RunTimeBeforeMatchAttemptKind) {
actions_runtime_pre.push_back(a);
} else if (a->action_kind == Action::RunTimeOnlyIfMatchKind) {
@ -142,7 +142,7 @@ bool Rule::evaluate(Assay *assay) {
for (Action *a :
this->actions_runtime_pos) {
assay->debug(4, "Running action: " + a->action);
a->evaluate(assay);
a->evaluate(this, assay);
}
if (this->chained && this->chainedRule == NULL) {
assay->debug(4, "Rule is marked as chained but there " \

View File

@ -40,13 +40,20 @@ Regex::Regex(const std::string& pattern_)
int regex_search(const std::string& s, SMatch *match,
const Regex& regex) {
std::string m;
pcrecpp::RE re(regex.pattern,
pcrecpp::RE_Options(PCRE_DOTALL|PCRE_MULTILINE));
/** FIXME: Should be not necessary to call PartialMatch twice here. */
match->size_ = re.PartialMatch(s);
re.PartialMatch(s, &m);
match->match = m;
return match->size_;
}
int regex_search(const std::string& s, Regex regex) {
std::string match;
pcrecpp::RE re(regex.pattern);
return re.PartialMatch(s);
}

View File

@ -37,6 +37,7 @@ class SMatch {
SMatch() : size_(0) { }
size_t size() { return size_; }
int size_;
std::string match;
};

51
src/variables/tx.cc Normal file
View File

@ -0,0 +1,51 @@
/*
* 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 "variables/tx.h"
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <utility>
#include "modsecurity/assay.h"
namespace ModSecurity {
namespace Variables {
std::list<std::pair<std::string, std::string>>
Tx::evaluate(Assay *assay) {
std::list<std::pair<std::string, std::string>> resl;
std::pair<std::string, std::string> pair;
pair = std::make_pair(std::string("TX:0"),
std::string("teste"));
resl.push_back(pair);
return resl;
}
} // namespace Variables
} // namespace ModSecurity

44
src/variables/tx.h Normal file
View File

@ -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 <iostream>
#include <string>
#include <vector>
#include <list>
#include <utility>
#ifndef SRC_VARIABLES_TX_H_
#define SRC_VARIABLES_TX_H_
#include "variables/variable.h"
namespace ModSecurity {
class Assay;
namespace Variables {
class Tx : public Variable {
public:
explicit Tx(std::string _name)
: Variable(_name) { }
std::list<std::pair<std::string, std::string>>
evaluate(Assay *assay) override;
};
} // namespace Variables
} // namespace ModSecurity
#endif // SRC_VARIABLES_TX_H_

View File

@ -0,0 +1,87 @@
[
{
"enabled":1,
"version_min":300000,
"title":"Testing Variables :: TX:0 (1/2)",
"client":{
"ip":"200.249.12.31",
"port":123
},
"server":{
"ip":"200.249.12.11",
"port":80
},
"request":{
"headers":{
"Host":"localhost",
"User-Agent":"curl/7.38.0",
"Accept":"*/*",
"Content-Length":"27",
"Content-Type":"application/x-www-form-urlencoded"
},
"uri":"/one/two/three?key1=value1&key2=v%20a%20l%20u%20e%202",
"protocol":"GET"
},
"response":{
"headers":{
"Date":"Mon, 13 Jul 2015 20:02:41 GMT",
"Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT",
"Content-Type":"text/html"
},
"body":[
"whee test 123"
]
},
"expected":{
"debug_log":"(.*) Target value: \"123\" \\(Variable\\: TX\\:0(.*)"
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"SecRequestBodyAccess On",
"SecRule RESPONSE_BODY \"@rx ([0-9]+)\" \"phase:4,capture,id:105\"",
"SecRule TX \"@rx ([A-z]+)\" \"phase:4,id:106\""
]
},
{
"enabled":1,
"version_min":300000,
"title":"Testing Variables :: TX:0 (2/2)",
"client":{
"ip":"200.249.12.31",
"port":123
},
"server":{
"ip":"200.249.12.31",
"port":80
},
"request":{
"headers":{
"Cookie":"USER_TOKEN=Yes; a=z; t=b"
},
"uri":"/?key=value&key=other_value",
"protocol":"GET"
},
"response":{
"headers":{
"Date":"Mon, 13 Jul 2015 20:02:41 GMT",
"Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT",
"Content-Type":"text/html"
},
"body":[
"no need."
]
},
"expected":{
"debug_log":"Target value: \"USER_TOKEN\" \\(Variable: TX:0(.*)"
},
"rules":[
"SecRuleEngine On",
"SecDebugLog \/tmp\/modsec_debug.log",
"SecDebugLogLevel 9",
"SecRule REQUEST_HEADERS \"@rx ([A-z]+)\" \"log,pass,capture,id:14\"",
"SecRule TX:0 \"@rx ([A-z]+)\" \"id:15\""
]
}
]