mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 05:45:59 +03:00
Adds checks for the NO_LOGS definition and improved the vars resolution time
This commit is contained in:
parent
3e067e7409
commit
ed86c24df6
@ -136,7 +136,7 @@ class ModSecurityStringVariables :
|
||||
l.push_back(pair);
|
||||
}
|
||||
|
||||
if (l.size() == 0) {
|
||||
if (l.size() == 0 && key.find(":") == std::string::npos) {
|
||||
for (auto& x : *this) {
|
||||
if ((x.first.substr(0, key.size() + 1).compare(key + ":") != 0)
|
||||
&& (x.first != key)) {
|
||||
@ -144,10 +144,8 @@ class ModSecurityStringVariables :
|
||||
}
|
||||
std::list<std::pair<std::string, std::string>> t;
|
||||
t = this->resolveVariable(x.first);
|
||||
for (std::pair<std::string, std::string> z : t) {
|
||||
pair = std::make_pair(std::string(z.first),
|
||||
std::string(z.second));
|
||||
l.push_back(pair);
|
||||
if (t.empty() == false) {
|
||||
l.insert(l.end(), t.begin(), t.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -239,8 +237,9 @@ class Assay {
|
||||
|
||||
ModSecurityStringVariables m_variables_strings;
|
||||
std::unordered_map<std::string, ModSecurityStringVariables *> collections;
|
||||
|
||||
#ifndef NO_LOGS
|
||||
void debug(int, std::string);
|
||||
#endif
|
||||
void serverLog(const std::string& msg);
|
||||
std::vector<actions::Action *> actions;
|
||||
|
||||
|
@ -33,7 +33,9 @@ Block::Block(std::string action)
|
||||
|
||||
|
||||
bool Block::evaluate(Rule *rule, Assay *assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(8, "Running action block");
|
||||
#endif
|
||||
for (Action *a : rule->actions_runtime_pos) {
|
||||
if (a->isDisruptive() == true) {
|
||||
assay->actions.push_back(a);
|
||||
|
@ -35,17 +35,16 @@ bool Capture::evaluate(Rule *rule, Assay *assay) {
|
||||
std::list<std::string> match;
|
||||
|
||||
operators::Pm *pm = dynamic_cast<operators::Pm *>(op);
|
||||
operators::Rx *rx = dynamic_cast<operators::Rx *>(op);
|
||||
operators::Contains *contains = dynamic_cast<operators::Contains *>(op);
|
||||
|
||||
if (pm != NULL) {
|
||||
match = pm->matched;
|
||||
}
|
||||
|
||||
operators::Rx *rx = dynamic_cast<operators::Rx *>(op);
|
||||
if (rx != NULL) {
|
||||
match = rx->matched;
|
||||
}
|
||||
|
||||
operators::Contains *contains = dynamic_cast<operators::Contains *>(op);
|
||||
if (contains != NULL) {
|
||||
match = contains->matched;
|
||||
}
|
||||
|
@ -31,7 +31,9 @@ Deny::Deny(std::string action)
|
||||
|
||||
|
||||
bool Deny::evaluate(Rule *rule, Assay *assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(8, "Running action deny");
|
||||
#endif
|
||||
assay->actions.push_back(this);
|
||||
return true;
|
||||
}
|
||||
|
@ -36,7 +36,9 @@ LogData::LogData(std::string action)
|
||||
|
||||
bool LogData::evaluate(Rule *rule, Assay *assay) {
|
||||
std::string msg = MacroExpansion::expand(m_data, assay);
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(9, "Saving msg: " + msg);
|
||||
#endif
|
||||
assay->rulesMessages.push_back(msg);
|
||||
assay->serverLog(msg);
|
||||
return true;
|
||||
|
@ -36,7 +36,9 @@ Msg::Msg(std::string action)
|
||||
|
||||
bool Msg::evaluate(Rule *rule, Assay *assay) {
|
||||
std::string msg = MacroExpansion::expand(m_msg, assay);
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(9, "Saving msg: " + msg);
|
||||
#endif
|
||||
assay->rulesMessages.push_back(msg);
|
||||
assay->serverLog(msg);
|
||||
return true;
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "modsecurity/assay.h"
|
||||
#include "src/rule.h"
|
||||
#include "src/macro_expansion.h"
|
||||
#include "src/utils.h"
|
||||
|
||||
namespace ModSecurity {
|
||||
namespace actions {
|
||||
@ -57,6 +58,7 @@ bool SetVar::init(std::string *error) {
|
||||
pos = action.find(".");
|
||||
if (pos != std::string::npos) {
|
||||
collectionName = std::string(action, 0, pos);
|
||||
collectionName = toupper(collectionName);
|
||||
} else {
|
||||
error->assign("Missing the collection and/or variable name");
|
||||
return false;
|
||||
@ -140,8 +142,10 @@ bool SetVar::evaluate(Rule *rule, Assay *assay) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(8, "Saving variable: " + collectionName + ":" + \
|
||||
variableName + " with value: " + targetValue);
|
||||
#endif
|
||||
assay->setCollection(collectionName, variableName, targetValue);
|
||||
|
||||
return true;
|
||||
|
@ -51,9 +51,11 @@ Severity::Severity(std::string action)
|
||||
|
||||
|
||||
bool Severity::evaluate(Rule *rule, Assay *assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(9, "This rule severity is: " + \
|
||||
std::to_string(this->m_severity) + " current assay is: " + \
|
||||
std::to_string(assay->highest_severity));
|
||||
#endif
|
||||
|
||||
if (assay->highest_severity > this->m_severity) {
|
||||
assay->highest_severity = this->m_severity;
|
||||
|
@ -32,7 +32,9 @@ SkipAfter::SkipAfter(std::string action)
|
||||
|
||||
|
||||
bool SkipAfter::evaluate(Rule *rule, Assay *assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(5, "Setting skipAfter for: " + m_marker);
|
||||
#endif
|
||||
assay->m_marker = m_marker;
|
||||
return true;
|
||||
}
|
||||
|
@ -36,7 +36,9 @@ Tag::Tag(std::string action)
|
||||
|
||||
bool Tag::evaluate(Rule *rule, Assay *assay) {
|
||||
std::string tag = MacroExpansion::expand(m_tag, assay);
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(9, "Rule tag: " + tag);
|
||||
#endif
|
||||
assay->ruleTags.push_back(tag);
|
||||
return true;
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ std::string Base64Decode::evaluate(std::string value,
|
||||
* @todo Implement the transformation base64decode
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation 64 is not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,8 +41,10 @@ std::string Base64DecodeExt::evaluate(std::string value,
|
||||
* @todo Implement the transformation Base64DecodeExt
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation Base64DecodeExt is" \
|
||||
" not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ std::string CmdLine::evaluate(std::string value,
|
||||
* @todo Implement the transformation CmdLine
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation CmdLine is not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,8 +41,10 @@ std::string CompressWhitespace::evaluate(std::string value,
|
||||
* @todo Implement the transformation CompressWhitespace
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation CompressWhitespace is " \
|
||||
"not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,8 +41,10 @@ std::string EscapeSeqDecode::evaluate(std::string value,
|
||||
* @todo Implement the transformation EscapeSeqDecode
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation EscapeSeqDecode is " \
|
||||
"not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ std::string HexDecode::evaluate(std::string value,
|
||||
* @todo Implement the transformation HexDecode
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation HexDecode is not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ std::string HexEncode::evaluate(std::string value,
|
||||
* @todo Implement the transformation HexEncode
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation HexEncode is not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ std::string Length::evaluate(std::string value,
|
||||
* @todo Implement the transformation Length
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation Length is not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ std::string Md5::evaluate(std::string value,
|
||||
* @todo Implement the transformation Md5
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation Md5 is not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,8 +41,10 @@ std::string NormalisePath::evaluate(std::string value,
|
||||
* @todo Implement the transformation NormalisePath
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation NormalisePath is not" \
|
||||
" implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,8 +41,10 @@ std::string ParityEven7bit::evaluate(std::string value,
|
||||
* @todo Implement the transformation ParityEven7bit
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation ParityEven7bit is not" \
|
||||
" implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,8 +41,10 @@ std::string ParityOdd7bit::evaluate(std::string value,
|
||||
* @todo Implement the transformation ParityOdd7bit
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation ParityOdd7bit is not " \
|
||||
"implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,8 +41,10 @@ std::string ParityZero7bit::evaluate(std::string value,
|
||||
* @todo Implement the transformation ParityZero7bit
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation ParityZero7bit is not" \
|
||||
"implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,8 +41,10 @@ std::string RemoveComments::evaluate(std::string value,
|
||||
* @todo Implement the transformation RemoveComments
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation RemoveComments is not " \
|
||||
"implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,8 +41,10 @@ std::string RemoveCommentsChar::evaluate(std::string value,
|
||||
* @todo Implement the transformation RemoveCommentsChar
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation RemoveCommentsChar " \
|
||||
"is not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,8 +41,10 @@ std::string RemoveWhitespace::evaluate(std::string value,
|
||||
* @todo Implement the transformation RemoveWhitespace
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation RemoveWhitespace is " \
|
||||
"not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,8 +41,10 @@ std::string ReplaceComments::evaluate(std::string value,
|
||||
* @todo Implement the transformation ReplaceComments
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation ReplaceComments " \
|
||||
"is not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ std::string ReplaceNulls::evaluate(std::string value,
|
||||
* @todo Implement the transformation ReplaceNulls
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation ReplaceNulls is not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ std::string Sha1::evaluate(std::string value,
|
||||
* @todo Implement the transformation Sha1
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation Sha1 is not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ std::string SqlHexDecode::evaluate(std::string value,
|
||||
* @todo Implement the transformation SqlHexDecode
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation SqlHexDecode is not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ std::string UrlDecode::evaluate(std::string value,
|
||||
* @todo Implement the transformation UrlDecode
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation UrlDecode is not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ std::string UrlEncode::evaluate(std::string value,
|
||||
* @todo Implement the transformation UrlEncode
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation UrlEncode is not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ std::string Utf8Unicode::evaluate(std::string value,
|
||||
* @todo Implement the transformation Utf8Unicode
|
||||
*/
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Transformation Utf8Unicode is not implemented yet.");
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
130
src/assay.cc
130
src/assay.cc
@ -127,7 +127,9 @@ Assay::Assay(ModSecurity *ms, Rules *rules, void *logCbData)
|
||||
"RESPONSE_HEADERS_NAMES");
|
||||
|
||||
collections.emplace("TX", new ModSecurityStringVariables());
|
||||
#ifndef NO_LOGS
|
||||
this->debug(4, "Initialising transaction");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -157,6 +159,7 @@ Assay::~Assay() {
|
||||
* @param message Message to be logged.
|
||||
*
|
||||
*/
|
||||
#ifndef NO_LOGS
|
||||
void Assay::debug(int level, std::string message) {
|
||||
if (m_rules == NULL) {
|
||||
return;
|
||||
@ -164,7 +167,7 @@ void Assay::debug(int level, std::string message) {
|
||||
|
||||
m_rules->debug(level, message);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name processConnection
|
||||
@ -193,8 +196,10 @@ int Assay::processConnection(const char *client, int cPort, const char *server,
|
||||
this->m_serverIpAddress = server;
|
||||
this->m_clientPort = cPort;
|
||||
this->m_serverPort = sPort;
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Transaction context created.");
|
||||
debug(4, "Starting phase CONNECTION. (SecRules 0)");
|
||||
#endif
|
||||
|
||||
this->store_variable("REMOTE_HOST", m_clientIpAddress);
|
||||
this->store_variable("UNIQUE_ID", id);
|
||||
@ -232,7 +237,10 @@ int Assay::processConnection(const char *client, int cPort, const char *server,
|
||||
*/
|
||||
int Assay::processURI(const char *uri, const char *protocol,
|
||||
const char *http_version) {
|
||||
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Starting phase URI. (SecRules 0 + 1/2)");
|
||||
#endif
|
||||
|
||||
m_protocol = protocol;
|
||||
m_httpVersion = http_version;
|
||||
@ -326,9 +334,10 @@ int Assay::processURI(const char *uri, const char *protocol,
|
||||
key.length() + value.length();
|
||||
this->m_ARGScombinedSizeStr->assign(
|
||||
std::to_string(this->m_ARGScombinedSize));
|
||||
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Adding request argument (QUERY_STRING): name \"" + \
|
||||
key + "\", value \"" + value + "\"");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -350,10 +359,14 @@ int Assay::processURI(const char *uri, const char *protocol,
|
||||
*
|
||||
*/
|
||||
int Assay::processRequestHeaders() {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Starting phase REQUEST_HEADERS. (SecRules 1)");
|
||||
#endif
|
||||
|
||||
if (m_rules->secRuleEngine == Rules::DisabledRuleEngine) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Rule engine disabled, returning...");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -502,10 +515,14 @@ int Assay::addRequestHeader(const unsigned char *key, size_t key_n,
|
||||
*
|
||||
*/
|
||||
int Assay::processRequestBody() {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Starting phase REQUEST_BODY. (SecRules 2)");
|
||||
#endif
|
||||
|
||||
if (m_rules->secRuleEngine == Rules::DisabledRuleEngine) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Rule engine disabled, returning...");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -538,41 +555,56 @@ int Assay::processRequestBody() {
|
||||
store_variable("MULTIPART_CRLF_LF_LINES", "0");
|
||||
}
|
||||
if (m.boundaryStartsWithWhiteSpace) {
|
||||
#ifndef NO_LOGS
|
||||
debug(9, "Multipart: Boundary starts with white space, " \
|
||||
"setting MULTIPART_STRICT_ERROR to 1");
|
||||
#endif
|
||||
update_variable_first("MULTIPART_STRICT_ERROR", "1");
|
||||
}
|
||||
if (m.boundaryIsQuoted) {
|
||||
#ifndef NO_LOGS
|
||||
|
||||
debug(9, "Multipart: Boundary is quoted, " \
|
||||
"setting MULTIPART_STRICT_ERROR to 1");
|
||||
#endif
|
||||
update_variable_first("MULTIPART_STRICT_ERROR", "1");
|
||||
}
|
||||
if (m.containsDataAfter) {
|
||||
#ifndef NO_LOGS
|
||||
debug(9, "Multipart: There is data after the boundary, " \
|
||||
"setting MULTIPART_STRICT_ERROR to 1");
|
||||
#endif
|
||||
update_variable_first("MULTIPART_STRICT_ERROR", "1");
|
||||
store_variable("MULTIPART_UNMATCHED_BOUNDARY", "1");
|
||||
} else {
|
||||
store_variable("MULTIPART_UNMATCHED_BOUNDARY", "0");
|
||||
}
|
||||
if (m.containsDataBefore) {
|
||||
#ifndef NO_LOGS
|
||||
debug(9, "Multipart: There is data before the boundary, " \
|
||||
"setting MULTIPART_STRICT_ERROR to 1");
|
||||
#endif
|
||||
update_variable_first("MULTIPART_STRICT_ERROR", "1");
|
||||
}
|
||||
if (m.lf) {
|
||||
#ifndef NO_LOGS
|
||||
debug(9, "Multipart: Lines are LF-terminated, " \
|
||||
"setting MULTIPART_STRICT_ERROR to 1");
|
||||
#endif
|
||||
update_variable_first("MULTIPART_STRICT_ERROR", "1");
|
||||
}
|
||||
if (m.missingSemicolon) {
|
||||
#ifndef NO_LOGS
|
||||
debug(9, "Multipart: Boundary missing semicolon, " \
|
||||
"setting MULTIPART_STRICT_ERROR to 1");
|
||||
#endif
|
||||
update_variable_first("MULTIPART_STRICT_ERROR", "1");
|
||||
}
|
||||
if (m.invalidQuote) {
|
||||
#ifndef NO_LOGS
|
||||
debug(9, "Multipart: Invalid quote, " \
|
||||
"setting MULTIPART_STRICT_ERROR to 1");
|
||||
#endif
|
||||
update_variable_first("MULTIPART_STRICT_ERROR", "1");
|
||||
}
|
||||
}
|
||||
@ -682,7 +714,9 @@ int Assay::requestBodyFromFile(const char *path) {
|
||||
std::string str;
|
||||
|
||||
if (request_body.is_open() == false) {
|
||||
#ifndef NO_LOGS
|
||||
debug(3, "Failed to open request body at: " + std::string(path));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -695,8 +729,10 @@ int Assay::requestBodyFromFile(const char *path) {
|
||||
const char *buf = str.c_str();
|
||||
int len = request_body.tellg();
|
||||
|
||||
#ifndef NO_LOGS
|
||||
debug(9, "Adding request body: " + std::to_string(len) + " bytes. " \
|
||||
"Limit set to: " + std::to_string(this->m_rules->requestBodyLimit));
|
||||
#endif
|
||||
|
||||
return appendRequestBody(reinterpret_cast<const unsigned char*>(buf), len);
|
||||
}
|
||||
@ -704,25 +740,33 @@ int Assay::requestBodyFromFile(const char *path) {
|
||||
int Assay::appendRequestBody(const unsigned char *buf, size_t len) {
|
||||
int current_size = this->m_requestBody.tellp();
|
||||
|
||||
#ifndef NO_LOGS
|
||||
debug(9, "Appending request body: " + std::to_string(len) + " bytes. " \
|
||||
"Limit set to: " + std::to_string(this->m_rules->requestBodyLimit));
|
||||
#endif
|
||||
|
||||
if (this->m_rules->requestBodyLimit > 0
|
||||
&& this->m_rules->requestBodyLimit < len + current_size) {
|
||||
store_variable("INBOUND_DATA_ERROR", "1");
|
||||
#ifndef NO_LOGS
|
||||
debug(5, "Request body is bigger than the maximum expected.");
|
||||
#endif
|
||||
if (this->m_rules->requestBodyLimitAction ==
|
||||
Rules::BodyLimitAction::ProcessPartialBodyLimitAction) {
|
||||
size_t spaceLeft = this->m_rules->requestBodyLimit - current_size;
|
||||
this->m_requestBody.write(reinterpret_cast<const char*>(buf),
|
||||
spaceLeft);
|
||||
#ifndef NO_LOGS
|
||||
debug(5, "Request body limit is marked to process partial");
|
||||
#endif
|
||||
return false;
|
||||
} else {
|
||||
if (this->m_rules->requestBodyLimitAction ==
|
||||
Rules::BodyLimitAction::RejectBodyLimitAction) {
|
||||
#ifndef NO_LOGS
|
||||
debug(5, "Request body limit is marked to reject the " \
|
||||
"request");
|
||||
#endif
|
||||
Action *a = new actions::Deny("deny");
|
||||
a->temporaryAction = true;
|
||||
actions.push_back(a);
|
||||
@ -752,10 +796,14 @@ int Assay::appendRequestBody(const unsigned char *buf, size_t len) {
|
||||
*
|
||||
*/
|
||||
int Assay::processResponseHeaders() {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Starting phase RESPONSE_HEADERS. (SecRules 3)");
|
||||
#endif
|
||||
|
||||
if (m_rules->secRuleEngine == Rules::DisabledRuleEngine) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Rule engine disabled, returning...");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -869,10 +917,14 @@ int Assay::addResponseHeader(const unsigned char *key, size_t key_n,
|
||||
*
|
||||
*/
|
||||
int Assay::processResponseBody() {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Starting phase RESPONSE_BODY. (SecRules 4)");
|
||||
#endif
|
||||
|
||||
if (m_rules->secRuleEngine == Rules::DisabledRuleEngine) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Rule engine disabled, returning...");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -910,26 +962,34 @@ int Assay::processResponseBody() {
|
||||
int Assay::appendResponseBody(const unsigned char *buf, size_t len) {
|
||||
int current_size = this->m_responseBody.tellp();
|
||||
|
||||
#ifndef NO_LOGS
|
||||
debug(9, "Appending response body: " + std::to_string(len + current_size)
|
||||
+ " bytes. Limit set to: " +
|
||||
std::to_string(this->m_rules->responseBodyLimit));
|
||||
#endif
|
||||
|
||||
if (this->m_rules->responseBodyLimit > 0
|
||||
&& this->m_rules->responseBodyLimit < len + current_size) {
|
||||
store_variable("OUTBOUND_DATA_ERROR", "1");
|
||||
#ifndef NO_LOGS
|
||||
debug(5, "Response body is bigger than the maximum expected.");
|
||||
#endif
|
||||
if (this->m_rules->responseBodyLimitAction ==
|
||||
Rules::BodyLimitAction::ProcessPartialBodyLimitAction) {
|
||||
size_t spaceLeft = this->m_rules->responseBodyLimit - current_size;
|
||||
this->m_responseBody.write(reinterpret_cast<const char*>(buf),
|
||||
spaceLeft);
|
||||
#ifndef NO_LOGS
|
||||
debug(5, "Response body limit is marked to process partial");
|
||||
#endif
|
||||
return false;
|
||||
} else {
|
||||
if (this->m_rules->responseBodyLimitAction ==
|
||||
Rules::BodyLimitAction::RejectBodyLimitAction) {
|
||||
#ifndef NO_LOGS
|
||||
debug(5, "Response body limit is marked to reject the " \
|
||||
"request");
|
||||
#endif
|
||||
Action *a = new actions::Deny("deny");
|
||||
a->temporaryAction = true;
|
||||
actions.push_back(a);
|
||||
@ -1005,10 +1065,14 @@ int Assay::getResponseBodyLenth() {
|
||||
*
|
||||
*/
|
||||
int Assay::processLogging(int returned_code) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Starting phase LOGGING. (SecRules 5)");
|
||||
#endif
|
||||
|
||||
if (m_rules->secRuleEngine == Rules::DisabledRuleEngine) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Rule engine disabled, returning...");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1017,12 +1081,16 @@ int Assay::processLogging(int returned_code) {
|
||||
|
||||
/* If relevant, save this assay information at the audit_logs */
|
||||
if (m_rules != NULL && m_rules->audit_log != NULL) {
|
||||
#ifndef NO_LOGS
|
||||
debug(8, "Checking if this request is suitable to be saved as an audit log.");
|
||||
#endif
|
||||
int parts = -1;
|
||||
|
||||
if (this->auditLogModifier.size() > 0)
|
||||
{
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "There was an audit log modifier for this transaction.");
|
||||
#endif
|
||||
std::list<std::pair<int, std::string>>::iterator it;
|
||||
parts = this->m_rules->audit_log->m_parts;
|
||||
for (it = auditLogModifier.begin(); it != auditLogModifier.end(); ++it) {
|
||||
@ -1034,6 +1102,7 @@ int Assay::processLogging(int returned_code) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef NO_LOGS
|
||||
if (save_in_auditlog) {
|
||||
debug(8, "This request was marked to be saved via auditlog action.");
|
||||
}
|
||||
@ -1042,6 +1111,7 @@ int Assay::processLogging(int returned_code) {
|
||||
if (saved) {
|
||||
debug(8, "Request was relevant to be saved.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1079,6 +1149,7 @@ void Assay::cleanup() {
|
||||
bool Assay::intervention(ModSecurityIntervention *it) {
|
||||
it->status = 200;
|
||||
it->url = NULL;
|
||||
it->disruptive = false;
|
||||
if (actions.size() > 0) {
|
||||
for (Action *a : actions) {
|
||||
if (a->action_kind == Action::Kind::RunTimeOnlyIfMatchKind) {
|
||||
@ -1405,50 +1476,15 @@ std::list<std::pair<std::string, std::string>>
|
||||
std::list<std::pair<std::string, std::string>> l;
|
||||
std::pair<std::string, std::string> pair;
|
||||
|
||||
auto range = m_variables_strings.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.empty()) {
|
||||
for (auto &x : m_variables_strings) {
|
||||
if ((x.first.substr(0, var.size() + 1).compare(var + ":") != 0)
|
||||
&& (x.first != var)) {
|
||||
continue;
|
||||
}
|
||||
std::list<std::pair<std::string, std::string>> t;
|
||||
t = resolve_variable(x.first);
|
||||
for (std::pair<std::string, std::string> z : t) {
|
||||
pair = std::make_pair(std::string(z.first),
|
||||
std::string(z.second));
|
||||
l.push_back(pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
l = m_variables_strings.resolveVariable(var);
|
||||
|
||||
size_t ac = var.find(":");
|
||||
if (ac != std::string::npos) {
|
||||
/* It may be a collection */
|
||||
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.empty()) {
|
||||
for (auto &x : *a.second) {
|
||||
if ((x.first.substr(0, var.size() + 1).compare(var + ":") != 0)
|
||||
&& (x.first != var)) {
|
||||
continue;
|
||||
}
|
||||
std::list<std::pair<std::string, std::string>> t;
|
||||
t = resolve_variable(x.first);
|
||||
for (std::pair<std::string, std::string> z : t) {
|
||||
pair = std::make_pair(std::string(z.first),
|
||||
std::string(z.second));
|
||||
l.push_back(pair);
|
||||
}
|
||||
std::list<std::pair<std::string, std::string>> l2 = a.second->resolveVariable(var);
|
||||
if (l2.empty() == false) {
|
||||
l.insert(l.end(), l2.begin(), l2.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1500,12 +1536,14 @@ void Assay::setCollection(const std::string& collectionName,
|
||||
|
||||
try {
|
||||
ModSecurityStringVariables *collection;
|
||||
collection = collections.at(toupper(collectionName));
|
||||
collection->storeOrUpdateVariable(toupper(collectionName) + ":"
|
||||
collection = collections.at(collectionName);
|
||||
collection->storeOrUpdateVariable(collectionName + ":"
|
||||
+ variableName, targetValue);
|
||||
} catch (...) {
|
||||
#ifndef NO_LOGS
|
||||
debug(9, "don't know any collection named: "
|
||||
+ collectionName + ". it was created?");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -35,14 +35,18 @@ bool DetectSQLi::evaluate(Assay *assay, const std::string &input) {
|
||||
if (issqli) {
|
||||
// set_match_to_tx(msr, capture, fingerprint, 0);
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "detected SQLi using libinjection with " \
|
||||
"fingerprint '" + std::string(fingerprint) + "' at: '" +
|
||||
input + "'");
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(9, "detected SQLi: not able to find an inject on '" +
|
||||
input + "'");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,12 +32,16 @@ bool DetectXSS::evaluate(Assay *assay, const std::string &input) {
|
||||
|
||||
if (is_xss) {
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(5, "detected XSS using libinjection.");
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(9, "libinjection was not able to " \
|
||||
"find any XSS in: " + input);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,18 +67,24 @@ namespace operators {
|
||||
|
||||
|
||||
bool Operator::debug(Assay *assay, int x, std::string a) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(x, a);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Operator::evaluate(Assay *assay) {
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(2, "Operator: " + this->op + \
|
||||
" is not implemented or malfunctioning.");
|
||||
#endif
|
||||
} else {
|
||||
#ifndef NO_LOGS
|
||||
std::cerr << "Operator: " + this->op + \
|
||||
" is not implemented or malfunctioning.";
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -86,11 +92,15 @@ bool Operator::evaluate(Assay *assay) {
|
||||
|
||||
bool Operator::evaluate(Assay *assay, const std::string& a) {
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(2, "Operator: " + this->op + \
|
||||
" is not implemented or malfunctioning.");
|
||||
#endif
|
||||
} else {
|
||||
#ifndef NO_LOGS
|
||||
std::cerr << "Operator: " + this->op + \
|
||||
" is not implemented or malfunctioning.";
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -77,29 +77,37 @@ bool ValidateUrlEncoding::evaluate(Assay *assay, const std::string &input) {
|
||||
case 1 :
|
||||
/* Encoding is valid */
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(7, "Valid URL Encoding at '" +input + "'");
|
||||
#endif
|
||||
}
|
||||
res = false;
|
||||
break;
|
||||
case -2 :
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(7, "Invalid URL Encoding: Non-hexadecimal "
|
||||
"digits used at '" + input + "'");
|
||||
#endif
|
||||
}
|
||||
res = true; /* Invalid match. */
|
||||
break;
|
||||
case -3 :
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(7, "Invalid URL Encoding: Not enough characters "
|
||||
"at the end of input at '" + input + "'");
|
||||
#endif
|
||||
}
|
||||
res = true; /* Invalid match. */
|
||||
break;
|
||||
case -1 :
|
||||
default :
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(7, "Invalid URL Encoding: Internal Error (rc = " +
|
||||
std::to_string(rc) + ") at '" + input + "'");
|
||||
#endif
|
||||
}
|
||||
res = true;
|
||||
break;
|
||||
|
@ -125,45 +125,55 @@ bool ValidateUtf8Encoding::evaluate(Assay *assay, const std::string &str) {
|
||||
switch (rc) {
|
||||
case UNICODE_ERROR_CHARACTERS_MISSING :
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(8, "Invalid UTF-8 encoding: "
|
||||
"not enough bytes in character "
|
||||
"at " + str + ". [offset \"" +
|
||||
std::to_string(i) + "\"]");
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case UNICODE_ERROR_INVALID_ENCODING :
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(8, "Invalid UTF-8 encoding: "
|
||||
"invalid byte value in character "
|
||||
"at " + str + ". [offset \"" +
|
||||
std::to_string(i) + "\"]");
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case UNICODE_ERROR_OVERLONG_CHARACTER :
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(8, "Invalid UTF-8 encoding: "
|
||||
"overlong character detected "
|
||||
"at " + str + ". [offset \"" +
|
||||
std::to_string(i) + "\"]");
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case UNICODE_ERROR_RESTRICTED_CHARACTER :
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(8, "Invalid UTF-8 encoding: "
|
||||
"use of restricted character "
|
||||
"at " + str + ". [offset \"" +
|
||||
std::to_string(i) + "\"]");
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case UNICODE_ERROR_DECODING_ERROR :
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(8, "Error validating UTF-8 decoding "
|
||||
"at " + str + ". [offset \"" +
|
||||
std::to_string(i) + "\"]");
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
@ -171,9 +181,11 @@ bool ValidateUtf8Encoding::evaluate(Assay *assay, const std::string &str) {
|
||||
|
||||
if (rc <= 0) {
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(8, "Internal error during UTF-8 validation "
|
||||
"at " + str + ". [offset \"" +
|
||||
std::to_string(i) + "\"]");
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -79,9 +79,11 @@ bool VerifyCC::evaluate(Assay *assay, const std::string &i) {
|
||||
is_cc = luhnVerify(match.c_str(), match.size());
|
||||
if (is_cc) {
|
||||
if (assay) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(9, "CC# match \"" + param +
|
||||
"\" at " + i + ". [offset " +
|
||||
std::to_string(offset) + "]");
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -40,15 +40,19 @@ Multipart::Multipart(std:: string header, Assay *assay)
|
||||
|
||||
bool Multipart::init() {
|
||||
if (m_header.length() > 1024) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Multipart: Invalid boundary in Content-Type (length).");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t boundary_pos = m_header.find("boundary");
|
||||
if (boundary_pos != std::string::npos &&
|
||||
m_header.find("boundary", boundary_pos + 1) != std::string::npos) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Multipart: Multiple boundary parameters in " \
|
||||
"Content-Type.");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -56,35 +60,47 @@ bool Multipart::init() {
|
||||
std::size_t semicolon_pos = boundary.find(";");
|
||||
if (semicolon_pos != std::string::npos
|
||||
&& boundary.find(";", semicolon_pos + 1) != std::string::npos) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Multipart: Invalid boundary in Content-Type. (malformed). " \
|
||||
"Too many semicolons.");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (semicolon_pos == std::string::npos) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Multipart: Missing semicolon.");
|
||||
#endif
|
||||
this->missingSemicolon = true;
|
||||
}
|
||||
|
||||
if (boundary.at(8) != '=') {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Multipart: Invalid boundary in Content-Type. (malformed). " \
|
||||
"Missing equals.");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (boundary.at(8 + 1) == ' ') {
|
||||
boundaryStartsWithWhiteSpace = true;
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Multipart: Boundary starts with a white space");
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((boundaryStartsWithWhiteSpace && boundary.at(8 + 2) == '"') ||
|
||||
(!boundaryStartsWithWhiteSpace && boundary.at(8 + 1) == '"')) {
|
||||
boundaryIsQuoted = true;
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Multipart: Boundary inside quotes");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (boundaryIsQuoted && boundary.at(boundary.length()-1) != '"') {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Multipart: Invalid boundary in Content-type (quote).");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -116,8 +132,10 @@ bool Multipart::init() {
|
||||
}
|
||||
|
||||
if (boundaryContainsOnlyValidCharacters() == false) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Multipart: Invalid boundary in Content-type " \
|
||||
"(invalid characters).");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -190,7 +208,9 @@ bool Multipart::process(std::string data) {
|
||||
double files_size = 0;
|
||||
|
||||
if (start != 0) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Multipart: Boundary was not the first thing.");
|
||||
#endif
|
||||
this->containsDataBefore = true;
|
||||
}
|
||||
while (start != std::string::npos) {
|
||||
@ -230,7 +250,9 @@ bool Multipart::process(std::string data) {
|
||||
int i = 0;
|
||||
for (std::string x : blobs) {
|
||||
i++;
|
||||
#ifndef NO_LOGS
|
||||
debug(5, "Multipart: Inspecting blob: " + std::to_string(i));
|
||||
#endif
|
||||
MultipartBlob m(x, this);
|
||||
|
||||
if (m.name.empty() == false) {
|
||||
@ -249,11 +271,15 @@ bool Multipart::process(std::string data) {
|
||||
variables.emplace("FILES_NAMES:" + name, name);
|
||||
variables.emplace("FILES_SIZES:" + name,
|
||||
std::to_string(m.content.size()));
|
||||
#ifndef NO_LOGS
|
||||
debug(5, "Multipart: Saving FILES_TMP_CONTENT:" + name + " variable.");
|
||||
#endif
|
||||
variables.emplace("FILES_TMP_CONTENT:" + name, m.content);
|
||||
files_size = files_size + m.content.size();
|
||||
if (m.invalidQuote) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Multipart: Found invalid quoting.");
|
||||
#endif
|
||||
this->invalidQuote = true;
|
||||
}
|
||||
}
|
||||
|
@ -45,10 +45,11 @@ class Multipart {
|
||||
bool boundaryIsQuoted;
|
||||
bool missingSemicolon;
|
||||
bool invalidQuote;
|
||||
|
||||
#ifndef NO_LOGS
|
||||
void debug(int a, std::string str) {
|
||||
m_assay->debug(a, str);
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
std::string m_boundary;
|
||||
std::string m_header;
|
||||
|
@ -37,14 +37,18 @@ bool MultipartBlob::processContent() {
|
||||
|
||||
end = m_blob.find("\n", offset);
|
||||
if (end == std::string::npos) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Missing end of line");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
std::string firstLine = std::string(m_blob, offset, end);
|
||||
offset = end + 1;
|
||||
end = m_blob.find("\n", offset);
|
||||
if (end == std::string::npos) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Missing end of line");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
std::string secondLine = std::string(m_blob, offset, end - offset);
|
||||
@ -63,7 +67,9 @@ bool MultipartBlob::processContent() {
|
||||
if (contentType.empty() == false) {
|
||||
end = m_blob.find_first_of("\n", offset);
|
||||
if (end == std::string::npos) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Missing end of line");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
offset = end + 1;
|
||||
@ -94,7 +100,9 @@ bool MultipartBlob::processContentDispositionLine(
|
||||
|
||||
if (dispositionLine.size() < 30 ||
|
||||
dispositionLine.compare(21, 9, "form-data") != 0) {
|
||||
#ifndef NO_LOGS
|
||||
debug(4, "Multipart: Content-Disposition is unknown");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -37,9 +37,12 @@ class MultipartBlob {
|
||||
std::string filename;
|
||||
std::string contentType;
|
||||
std::string content;
|
||||
|
||||
#ifndef NO_LOGS
|
||||
void debug(int a, std::string str) {
|
||||
m_parent->debug(a, str);
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
const std::string m_blob;
|
||||
Multipart *m_parent;
|
||||
|
50
src/rule.cc
50
src/rule.cc
@ -138,7 +138,9 @@ bool Rule::evaluateActions(Assay *assay) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Running unconditional rule.");
|
||||
#endif
|
||||
|
||||
if (none == 0) {
|
||||
/*
|
||||
@ -172,7 +174,9 @@ bool Rule::evaluateActions(Assay *assay) {
|
||||
|
||||
for (Action *a : this->actions_runtime_pos) {
|
||||
if (a->isDisruptive() == false) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Running (_non_ disruptive) action: " + a->action);
|
||||
#endif
|
||||
a->evaluate(this, assay);
|
||||
} else {
|
||||
containsDisruptive = true;
|
||||
@ -183,28 +187,36 @@ bool Rule::evaluateActions(Assay *assay) {
|
||||
if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind) {
|
||||
if (a->isDisruptive()) {
|
||||
if (containsDisruptive) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "(SecDefaultAction) " \
|
||||
"_ignoring_ action: " + a->action + \
|
||||
" (rule contains a disruptive action)");
|
||||
#endif
|
||||
} else {
|
||||
if (assay->m_rules->secRuleEngine
|
||||
== Rules::EnabledRuleEngine) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "(SecDefaultAction) " \
|
||||
"Running action: " + a->action + \
|
||||
" (rule _does not_ contains a " \
|
||||
"disruptive action)");
|
||||
#endif
|
||||
a->evaluate(this, assay);
|
||||
} else {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "(SecDefaultAction) " \
|
||||
"_Not_ running action: " + a->action + \
|
||||
". Rule _does not_ contains a " \
|
||||
"disruptive action, but SecRuleEngine is not On.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "(SecDefaultAction) Running action: " + \
|
||||
a->action);
|
||||
a->evaluate(this, assay);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -212,11 +224,15 @@ bool Rule::evaluateActions(Assay *assay) {
|
||||
for (Action *a : this->actions_runtime_pos) {
|
||||
if (a->isDisruptive()
|
||||
&& assay->m_rules->secRuleEngine == Rules::EnabledRuleEngine) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Running (disruptive) action: " + a->action);
|
||||
#endif
|
||||
a->evaluate(this, assay);
|
||||
} else if (a->isDisruptive()) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Not running disruptive action: " + \
|
||||
a->action + ". SecRuleEngine is not On");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,6 +251,7 @@ bool Rule::evaluate(Assay *assay) {
|
||||
return evaluateActions(assay);
|
||||
}
|
||||
|
||||
#ifndef NO_LOGS
|
||||
std::string eparam = MacroExpansion::expand(this->op->param, assay);
|
||||
|
||||
if (this->op->param != eparam) {
|
||||
@ -251,6 +268,7 @@ bool Rule::evaluate(Assay *assay) {
|
||||
+ Variable::to_s(variables) + ".");
|
||||
|
||||
clock_t begin = clock();
|
||||
#endif
|
||||
|
||||
std::list<std::string> exclusions;
|
||||
for (int i = 0; i < variables->size(); i++) {
|
||||
@ -281,8 +299,10 @@ bool Rule::evaluate(Assay *assay) {
|
||||
for (auto &v : e) {
|
||||
if (std::find(exclusions.begin(), exclusions.end(),
|
||||
v.first) != exclusions.end()) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(9, "Variable: " + v.first + " is part of the" +
|
||||
" exclusion list, skipping...");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
std::string value = v.second;
|
||||
@ -301,9 +321,11 @@ bool Rule::evaluate(Assay *assay) {
|
||||
for (Action *a : assay->m_rules->defaultActions[this->phase]) {
|
||||
if (a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) {
|
||||
value = a->evaluate(value, assay);
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(9, "(SecDefaultAction) T (" + \
|
||||
std::to_string(transformations) + ") " + \
|
||||
a->name + ": \"" + value +"\"");
|
||||
#endif
|
||||
transformations++;
|
||||
}
|
||||
}
|
||||
@ -313,9 +335,11 @@ bool Rule::evaluate(Assay *assay) {
|
||||
None *z = dynamic_cast<None *>(a);
|
||||
if (none == 0) {
|
||||
value = a->evaluate(value, assay);
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(9, " T (" + \
|
||||
std::to_string(transformations) + ") " + \
|
||||
a->name + ": \"" + value +"\"");
|
||||
#endif
|
||||
transformations++;
|
||||
}
|
||||
if (z != NULL) {
|
||||
@ -323,27 +347,35 @@ bool Rule::evaluate(Assay *assay) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(9, "Target value: \"" + limitTo(80, toHexIfNeeded(value)) + \
|
||||
"\" (Variable: " + v.first + ")");
|
||||
#endif
|
||||
|
||||
ret = this->op->evaluate(assay, value);
|
||||
|
||||
#ifndef NO_LOGS
|
||||
clock_t end = clock();
|
||||
double elapsed_secs = static_cast<double>(end - begin) \
|
||||
/ CLOCKS_PER_SEC;
|
||||
|
||||
assay->debug(4, "Operator completed in " + \
|
||||
std::to_string(elapsed_secs) + " seconds");
|
||||
#endif
|
||||
|
||||
if (ret) {
|
||||
bool containsDisruptive = false;
|
||||
bool chainResult = false;
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Rule returned 1.");
|
||||
#endif
|
||||
|
||||
for (Action *a :
|
||||
this->actions_runtime_pos) {
|
||||
if (a->isDisruptive() == false) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Running (_non_ disruptive) action: " + a->action);
|
||||
#endif
|
||||
a->evaluate(this, assay);
|
||||
} else {
|
||||
containsDisruptive = true;
|
||||
@ -351,11 +383,15 @@ bool Rule::evaluate(Assay *assay) {
|
||||
}
|
||||
|
||||
if (this->chained && this->chainedRule == NULL) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Rule is marked as chained but there " \
|
||||
"isn't a subsequent rule.");
|
||||
#endif
|
||||
}
|
||||
if (this->chained && this->chainedRule != NULL) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Executing chained rule.");
|
||||
#endif
|
||||
if (assay->update_variable_first("MATCHED_VAR",
|
||||
value) == false) {
|
||||
assay->store_variable("MATCHED_VAR", value);
|
||||
@ -378,27 +414,35 @@ bool Rule::evaluate(Assay *assay) {
|
||||
if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind) {
|
||||
if (a->isDisruptive()) {
|
||||
if (containsDisruptive) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "(SecDefaultAction) " \
|
||||
"_ignoring_ action: " + a->action + \
|
||||
" (rule contains a disruptive action)");
|
||||
#endif
|
||||
} else {
|
||||
if (assay->m_rules->secRuleEngine
|
||||
== Rules::EnabledRuleEngine) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "(SecDefaultAction) " \
|
||||
"Running action: " + a->action + \
|
||||
" (rule _does not_ contains a " \
|
||||
"disruptive action)");
|
||||
#endif
|
||||
a->evaluate(this, assay);
|
||||
} else {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "(SecDefaultAction) " \
|
||||
"_Not_ running action: " + a->action + \
|
||||
". Rule _does not_ contains a " \
|
||||
"disruptive action, but SecRuleEngine is not On.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "(SecDefaultAction) Running " \
|
||||
"action: " + a->action + "!!" + std::to_string(a->isDisruptive()));
|
||||
#endif
|
||||
a->evaluate(this, assay);
|
||||
}
|
||||
}
|
||||
@ -408,19 +452,25 @@ bool Rule::evaluate(Assay *assay) {
|
||||
if (a->isDisruptive()
|
||||
&& assay->m_rules->secRuleEngine
|
||||
== Rules::EnabledRuleEngine) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Running (disruptive) action: " + \
|
||||
a->action);
|
||||
#endif
|
||||
a->evaluate(this, assay);
|
||||
} else if (a->isDisruptive()) {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4,
|
||||
"Not running disruptive action: " + \
|
||||
a->action + ". SecRuleEngine is not On");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
#ifndef NO_LOGS
|
||||
assay->debug(4, "Rule returned 0.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ char ip[] = "200.249.12.31";
|
||||
char rules_file[] = "basic_rules.conf";
|
||||
|
||||
|
||||
#define NUM_REQUESTS 1000
|
||||
#define NUM_REQUESTS 10000
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i = 0;
|
||||
@ -79,10 +79,14 @@ int main(int argc, char *argv[]) {
|
||||
" (ModSecurity benchmark utility)");
|
||||
|
||||
rules = new ModSecurity::Rules();
|
||||
rules->loadFromUri(rules_file);
|
||||
if (rules->loadFromUri(rules_file) < 0) {
|
||||
std::cout << "Problems loading the rules..." << std::endl;
|
||||
std::cout << rules->parserError.str() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_REQUESTS; i++) {
|
||||
std::cout << "Proceding with request " << i << std::endl;
|
||||
std::cout << "Proceeding with request " << i << std::endl;
|
||||
|
||||
Assay *modsecAssay = new Assay(modsec, rules, NULL);
|
||||
modsecAssay->processConnection(ip, 12345, "127.0.0.1", 80);
|
||||
|
Loading…
x
Reference in New Issue
Block a user