diff --git a/Makefile.am b/Makefile.am index d68cfa2c..dfe92eb8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -274,4 +274,5 @@ TESTS+=test/test-cases/secrules-language-tests/operators/ipMatch.json TESTS+=test/test-cases/secrules-language-tests/operators/strmatch.json TESTS+=test/test-cases/secrules-language-tests/operators/detectXSS.json TESTS+=test/test-cases/secrules-language-tests/operators/eq.json +TESTS+=test/test-cases/regression/offset-variable.json diff --git a/headers/modsecurity/anchored_set_variable.h b/headers/modsecurity/anchored_set_variable.h index 3a829310..128aff93 100644 --- a/headers/modsecurity/anchored_set_variable.h +++ b/headers/modsecurity/anchored_set_variable.h @@ -75,6 +75,10 @@ class AnchoredSetVariable : public std::unordered_multimap *l); diff --git a/headers/modsecurity/anchored_variable.h b/headers/modsecurity/anchored_variable.h index 202e0caf..7810eb9e 100644 --- a/headers/modsecurity/anchored_variable.h +++ b/headers/modsecurity/anchored_variable.h @@ -47,8 +47,12 @@ class AnchoredVariable { void unset(); void set(const std::string &a, size_t offset); + void set(const std::string &a, size_t offset, size_t offsetLen); void append(const std::string &a, size_t offset, - bool spaceSeparator = false); + bool spaceSeparator = false); + void append(const std::string &a, size_t offset, + bool spaceSeparator, int size); + void evaluate(std::vector *l); std::string * evaluate(); std::unique_ptr resolveFirst(); diff --git a/headers/modsecurity/transaction.h b/headers/modsecurity/transaction.h index f9e99517..68f1337a 100644 --- a/headers/modsecurity/transaction.h +++ b/headers/modsecurity/transaction.h @@ -352,11 +352,6 @@ class Transaction : public TransactionAnchoredVariables { */ const char *m_httpVersion; - /** - * Holds the request method: GET, POST, HEAD ... - */ - const char *m_method; - /** * Holds the server IP Address */ diff --git a/headers/modsecurity/variable_origin.h b/headers/modsecurity/variable_origin.h index 7150df1a..37e1f8ef 100644 --- a/headers/modsecurity/variable_origin.h +++ b/headers/modsecurity/variable_origin.h @@ -40,7 +40,7 @@ class VariableOrigin { std::string toText() { std::string offset = std::to_string(m_offset); std::string len = std::to_string(m_length); - return "rr:" + offset + "," + len; + return "v" + offset + "," + len; } int m_length; diff --git a/src/anchored_set_variable.cc b/src/anchored_set_variable.cc index e938aad6..fe364686 100644 --- a/src/anchored_set_variable.cc +++ b/src/anchored_set_variable.cc @@ -49,6 +49,23 @@ void AnchoredSetVariable::unset() { } +void AnchoredSetVariable::set(const std::string &key, + const std::string &value, size_t offset, size_t len) { + std::unique_ptr origin(new VariableOrigin()); + std::string *v = new std::string(value); + std::string *k = new std::string(m_name + ":" + key); + collection::Variable *var = new collection::Variable(k, v); + + origin->m_offset = offset; + origin->m_length = len; + + var->m_dynamic_value = true; + var->m_dynamic = false; + var->m_orign.push_back(std::move(origin)); + emplace(key, var); +} + + void AnchoredSetVariable::set(const std::string &key, const std::string &value, size_t offset) { std::unique_ptr origin(new VariableOrigin()); diff --git a/src/anchored_variable.cc b/src/anchored_variable.cc index 90242836..9525610c 100644 --- a/src/anchored_variable.cc +++ b/src/anchored_variable.cc @@ -56,6 +56,18 @@ void AnchoredVariable::unset() { } +void AnchoredVariable::set(const std::string &a, size_t offset, + size_t offsetLen) { + std::unique_ptr origin(new VariableOrigin()); + + m_offset = offset; + m_value.assign(a.c_str(), a.size()); + origin->m_offset = offset; + origin->m_length = offsetLen; + m_var->m_orign.push_back(std::move(origin)); +} + + void AnchoredVariable::set(const std::string &a, size_t offset) { std::unique_ptr origin(new VariableOrigin()); @@ -84,6 +96,23 @@ void AnchoredVariable::append(const std::string &a, size_t offset, } +void AnchoredVariable::append(const std::string &a, size_t offset, + bool spaceSeparator, int size) { + std::unique_ptr origin( + new VariableOrigin()); + + if (spaceSeparator && !m_value.empty()) { + m_value.append(" " + a); + } else { + m_value.append(a); + } + m_offset = offset; + origin->m_offset = offset; + origin->m_length = size; + m_var->m_orign.push_back(std::move(origin)); +} + + void AnchoredVariable::evaluate(std::vector *l) { if (m_name.empty() || m_var == NULL || m_var->m_key == NULL || m_var->m_value == NULL || m_var->m_key->empty()) { diff --git a/src/audit_log/writer/parallel.cc b/src/audit_log/writer/parallel.cc index 3fa6d6fd..f324eedd 100644 --- a/src/audit_log/writer/parallel.cc +++ b/src/audit_log/writer/parallel.cc @@ -144,7 +144,7 @@ bool Parallel::write(Transaction *transaction, int parts, std::string *error) { std::ofstream myfile; std::string a(fileName.c_str()); - myfile.open (a); + myfile.open(a); myfile << log; myfile.close(); diff --git a/src/operators/operator.h b/src/operators/operator.h index b81fd0eb..dac8c0c8 100644 --- a/src/operators/operator.h +++ b/src/operators/operator.h @@ -78,10 +78,7 @@ class Operator { static void logOffset(RuleMessage *ruleMessage, int offset, int len) { if (ruleMessage) { - if (ruleMessage->m_reference.empty() == false) { - ruleMessage->m_reference.append(";"); - } - ruleMessage->m_reference.append("op:" + ruleMessage->m_reference.append("o" + std::to_string(offset) + "," + std::to_string(len)); } diff --git a/src/request_body_processor/json.h b/src/request_body_processor/json.h index 1ad0bb12..98ac6b91 100644 --- a/src/request_body_processor/json.h +++ b/src/request_body_processor/json.h @@ -13,6 +13,9 @@ * */ +#ifndef SRC_REQUEST_BODY_PROCESSOR_JSON_H_ +#define SRC_REQUEST_BODY_PROCESSOR_JSON_H_ + #ifdef WITH_YAJL @@ -24,8 +27,6 @@ #include "modsecurity/transaction.h" #include "modsecurity/rules.h" -#ifndef SRC_REQUEST_BODY_PROCESSOR_JSON_H_ -#define SRC_REQUEST_BODY_PROCESSOR_JSON_H_ namespace modsecurity { @@ -82,7 +83,6 @@ class JSON { } // namespace RequestBodyProcessor } // namespace modsecurity +#endif // WITH_YAJL #endif // SRC_REQUEST_BODY_PROCESSOR_JSON_H_ - -#endif // WITH_YAJL diff --git a/src/request_body_processor/multipart.cc b/src/request_body_processor/multipart.cc index 2754fd97..5cc5968d 100644 --- a/src/request_body_processor/multipart.cc +++ b/src/request_body_processor/multipart.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include "modsecurity/collection/collections.h" #include "modsecurity/rules.h" @@ -212,7 +213,7 @@ void Multipart::validate_quotes(const char *data) { } -int Multipart::parse_content_disposition(const char *c_d_value) { +int Multipart::parse_content_disposition(const char *c_d_value, int offset) { const char *p = NULL; /* accept only what we understand */ @@ -342,7 +343,8 @@ int Multipart::parse_content_disposition(const char *c_d_value) { if (name == "name") { validate_quotes(value.c_str()); - m_transaction->m_variableMultiPartName.set(value, value, 0); + m_transaction->m_variableMultiPartName.set(value, value, + offset + ((p - c_d_value) - value.size())); if (!m_mpp->m_name.empty()) { debug(4, "Multipart: Warning: Duplicate Content-Disposition " \ @@ -350,10 +352,12 @@ int Multipart::parse_content_disposition(const char *c_d_value) { return -14; } m_mpp->m_name.assign(value); + m_mpp->m_nameOffset = offset + ((p - c_d_value) - value.size()); debug(9, "Multipart: Content-Disposition name: " + value + "."); } else if (name == "filename") { validate_quotes(value.c_str()); - m_transaction->m_variableMultiPartFileName.set(value, value, 0); + m_transaction->m_variableMultiPartFileName.set(value, value, \ + offset + ((p - c_d_value) - value.size())); if (!m_mpp->m_filename.empty()) { debug(4, "Multipart: Warning: Duplicate Content-Disposition " \ @@ -361,6 +365,7 @@ int Multipart::parse_content_disposition(const char *c_d_value) { return -15; } m_mpp->m_filename.assign(value); + m_mpp->m_filenameOffset = offset + ((p - c_d_value) - value.size()); debug(9, "Multipart: Content-Disposition filename: " \ + value + "."); @@ -432,7 +437,7 @@ int Multipart::tmp_file_name(std::string *filename) const { } -int Multipart::process_part_data(std::string *error) { +int Multipart::process_part_data(std::string *error, size_t offset) { char *p = m_buf + (MULTIPART_BUF_SIZE - m_bufleft); char localreserve[2] = { '\0', '\0' }; /* initialized to quiet warning */ int bytes_reserved = 0; @@ -525,7 +530,11 @@ int Multipart::process_part_data(std::string *error) { return -1; } - m_mpp->m_tmp_file_size += m_reserve[0]; + m_mpp->m_tmp_file_size.first += m_reserve[0]; + if (m_mpp->m_tmp_file_size.second == 0) { + m_mpp->m_tmp_file_size.second = offset \ + - m_mpp->m_tmp_file_size.first; + } m_mpp->m_length += m_reserve[0]; } @@ -541,12 +550,26 @@ int Multipart::process_part_data(std::string *error) { return -1; } - m_mpp->m_tmp_file_size += (MULTIPART_BUF_SIZE - m_bufleft); + m_mpp->m_value.append(std::string(m_buf, + MULTIPART_BUF_SIZE - m_bufleft)); + m_mpp->m_valueOffset = offset - (MULTIPART_BUF_SIZE - m_bufleft); + + m_mpp->m_tmp_file_size.first += (MULTIPART_BUF_SIZE - m_bufleft); + if (m_mpp->m_tmp_file_size.second == 0) { + m_mpp->m_tmp_file_size.second = offset \ + - m_mpp->m_tmp_file_size.first; + } + m_mpp->m_length += (MULTIPART_BUF_SIZE - m_bufleft); } else { /* just keep track of the file size */ - m_mpp->m_tmp_file_size += (MULTIPART_BUF_SIZE - m_bufleft) \ + m_mpp->m_tmp_file_size.first += (MULTIPART_BUF_SIZE - m_bufleft) \ + m_reserve[0]; + if (m_mpp->m_tmp_file_size.second == 0) { + m_mpp->m_tmp_file_size.second = offset \ + - m_mpp->m_tmp_file_size.first; + } + m_mpp->m_length += (MULTIPART_BUF_SIZE - m_bufleft) + m_reserve[0]; } } else if (m_mpp->m_type == MULTIPART_FORMDATA) { @@ -573,7 +596,7 @@ int Multipart::process_part_data(std::string *error) { m_mpp->m_length += d.size(); } - m_mpp->m_value_parts.push_back(d); + m_mpp->m_value_parts.push_back(std::make_pair(d, m_buf_offset)); debug(9, "Multipart: Added data to variable: " + d); } else { @@ -601,7 +624,7 @@ int Multipart::process_part_data(std::string *error) { } -int Multipart::process_part_header(std::string *error) { +int Multipart::process_part_header(std::string *error, int offset) { int i, len; /* Check for nul bytes. */ @@ -614,6 +637,7 @@ int Multipart::process_part_header(std::string *error) { } } + i = 0; /* The buffer is data so increase the data length counter. */ m_reqbody_no_files_length += (MULTIPART_BUF_SIZE - m_bufleft); @@ -639,9 +663,10 @@ int Multipart::process_part_header(std::string *error) { "Content-Disposition header."); return false; } - header_value = m_mpp->m_headers.at("Content-Disposition"); + header_value = m_mpp->m_headers.at("Content-Disposition").second; - rc = parse_content_disposition(header_value.c_str()); + rc = parse_content_disposition(header_value.c_str(), + m_mpp->m_headers.at("Content-Disposition").first); if (rc < 0) { debug(1, "Multipart: Invalid Content-Disposition header (" + std::to_string(rc) + "): " + header_value); @@ -714,15 +739,17 @@ int Multipart::process_part_header(std::string *error) { m_flag_invalid_header_folding = 1; } data++; + i++; } new_value = std::string(data); utils::string::chomp(&new_value); /* update the header value in the table */ - header_value = m_mpp->m_headers.at(m_mpp->m_last_header_name); + header_value = m_mpp->m_headers.at( + m_mpp->m_last_header_name).second; new_value = header_value + " " + new_value; - m_mpp->m_headers.at(m_mpp->m_last_header_name) = new_value; + m_mpp->m_headers.at(m_mpp->m_last_header_name).second = new_value; debug(9, "Multipart: Continued folder header \"" \ + m_mpp->m_last_header_name + "\" with \"" \ @@ -742,6 +769,7 @@ int Multipart::process_part_header(std::string *error) { data = m_buf; while ((*data != ':') && (*data != '\0')) { data++; + i++; } if (*data == '\0') { debug(1, "Multipart: Invalid part header (colon missing): " \ @@ -763,8 +791,10 @@ int Multipart::process_part_header(std::string *error) { /* extract the value value */ data++; + i++; while ((*data == '\t') || (*data == ' ')) { data++; + i++; } header_value = std::string(data); utils::string::chomp(&header_value); @@ -780,7 +810,8 @@ int Multipart::process_part_header(std::string *error) { m_mpp->m_headers.emplace( - std::string(header_name), std::string(header_value)); + std::string(header_name), std::make_pair(offset - len + i, + std::string(header_value))); debug(9, "Multipart: Added part header \"" + header_name \ @@ -805,8 +836,11 @@ int Multipart::process_boundary(int last_part) { if (m_mpp->m_type != MULTIPART_FILE) { /* now construct a single string out of the parts */ - for (std::string &i : m_mpp->m_value_parts) { - m_mpp->m_value.append(i); + for (const auto &i : m_mpp->m_value_parts) { + if (m_mpp->m_valueOffset == 0) { + m_mpp->m_valueOffset = i.second; + } + m_mpp->m_value.append(i.first); } } @@ -986,6 +1020,7 @@ int Multipart::multipart_complete(std::string *error) { if (m->m_name.empty()) { continue; } + size_t offset = m_transaction->m_variableOffset + 1; if (m->m_type == MULTIPART_FILE) { std::string tmp_name; @@ -996,25 +1031,36 @@ int Multipart::multipart_complete(std::string *error) { if (!m->m_filename.empty()) { name.assign(m->m_filename); } + m_transaction->m_variableFiles.set(m->m_filename, - m->m_filename, 0); - m_transaction->m_variableFilesNames.set(m->m_name, - m->m_name, 0); + m->m_filename, m->m_filenameOffset); + + m_transaction->m_variableFilesNames.set(m->m_filename, + m->m_filename, m->m_filenameOffset); + m_transaction->m_variableFilesSizes.set(m->m_name, - std::to_string(m->m_tmp_file_size), 0); - m_transaction->m_variableFilesTmpContent.set(m->m_name, - m->m_value, 0); - m_transaction->m_variableFilesTmpContent.set(m->m_name, - m->m_value, 0); - m_transaction->m_variableFilesTmpNames.set(m->m_name, - m->m_value, 0); - file_combined_size = file_combined_size + m->m_tmp_file_size; + std::to_string(m->m_tmp_file_size.first), + m->m_tmp_file_size.second, + m->m_tmp_file_size.first); + + m_transaction->m_variableFilesTmpContent.set(m->m_filename, + m->m_value, m->m_valueOffset); + + m_transaction->m_variableFilesTmpNames.set(m->m_filename, + m->m_filename, m->m_filenameOffset); + + file_combined_size = file_combined_size + m->m_tmp_file_size.first; + + m_transaction->m_variableFilesCombinedSize.set( + std::to_string(file_combined_size), + m->m_tmp_file_size.second, m->m_tmp_file_size.first); } else { debug(4, "Adding request argument (BODY): name \"" + m->m_name + "\", value \"" + m->m_value + "\""); m_transaction->m_variableArgs.set(m->m_name, m->m_value, - m_transaction->m_variableOffset); - m_transaction->m_variableArgsPost.set(m->m_name, m->m_value, 0); + offset + m->m_valueOffset); + m_transaction->m_variableArgsPost.set(m->m_name, m->m_value, + offset + m->m_valueOffset); } #if 0 if (m_transaction->m_namesArgs->empty()) { @@ -1036,9 +1082,7 @@ int Multipart::multipart_complete(std::string *error) { std::to_string(m_transaction->->m_ARGScombinedSize)); #endif } - m_transaction->m_variableFilesCombinedSize.set( - std::to_string(file_combined_size), - m_transaction->m_variableOffset); + return true; } @@ -1256,12 +1300,13 @@ bool Multipart::init(std::string *error) { * Assuming that all data is on data. We are not processing chunks. * */ -bool Multipart::process(const std::string& data, std::string *error) { +bool Multipart::process(const std::string& data, std::string *error, + int offset) { const char *inptr = data.c_str(); unsigned int inleft = data.size(); + size_t z = 0; if (data.size() == 0) return true; - m_seen_data = true; if (m_is_complete) { @@ -1285,6 +1330,8 @@ bool Multipart::process(const std::string& data, std::string *error) { char c = *inptr; int process_buffer = 0; + z++; + if ((c == '\r') && (m_bufleft == 1)) { /* we don't want to take \r as the last byte in the buffer */ process_buffer = 1; @@ -1443,13 +1490,13 @@ bool Multipart::process(const std::string& data, std::string *error) { return false; } - if (process_part_header(error) < 0) { + if (process_part_header(error, offset + z) < 0) { m_flag_error = 1; return false; } } else { - if (process_part_data(error) < 0) { + if (process_part_data(error, offset + z) < 0) { m_flag_error = 1; return false; } diff --git a/src/request_body_processor/multipart.h b/src/request_body_processor/multipart.h index beb7df4b..6d819696 100644 --- a/src/request_body_processor/multipart.h +++ b/src/request_body_processor/multipart.h @@ -17,6 +17,7 @@ #include #include #include +#include #ifndef SRC_REQUEST_BODY_PROCESSOR_MULTIPART_H_ #define SRC_REQUEST_BODY_PROCESSOR_MULTIPART_H_ @@ -58,9 +59,14 @@ class MultipartPart { MultipartPart() : m_type(MULTIPART_FORMDATA), m_tmp_file_fd(0), - m_tmp_file_size(0), m_offset(0), - m_length(0) { } + m_filenameOffset(0), + m_nameOffset(0), + m_valueOffset(0), + m_length(0) { + m_tmp_file_size.first = 0; + m_tmp_file_size.second = 0; + } ~MultipartPart() { m_headers.clear(); @@ -72,10 +78,13 @@ class MultipartPart { /* the name */ std::string m_name; + size_t m_nameOffset; /* variables only, variable value */ std::string m_value; - std::list m_value_parts; + size_t m_valueOffset; + + std::list> m_value_parts; /* files only, the content type (where available) */ /* std::string m_content_type; */ @@ -83,13 +92,15 @@ class MultipartPart { /* files only, the name of the temporary file holding data */ std::string m_tmp_file_name; int m_tmp_file_fd; - unsigned int m_tmp_file_size; + std::pair m_tmp_file_size; /* files only, filename as supplied by the browser */ std::string m_filename; + size_t m_filenameOffset; std::string m_last_header_name; - std::unordered_map m_headers; + std::unordered_map, + MyHash, MyEqual> m_headers; unsigned int m_offset; unsigned int m_length; @@ -108,11 +119,11 @@ class Multipart { int is_token_char(unsigned char c); int multipart_complete(std::string *err); - int parse_content_disposition(const char *c_d_value); - bool process(const std::string& data, std::string *err); + int parse_content_disposition(const char *c_d_value, int offset); + bool process(const std::string& data, std::string *err, int offset); int process_boundary(int last_part); - int process_part_header(std::string *error); - int process_part_data(std::string *error); + int process_part_header(std::string *error, int offset); + int process_part_data(std::string *error, size_t offset); int tmp_file_name(std::string *filename) const; diff --git a/src/rule.cc b/src/rule.cc index 6bb0a0ba..673b4af3 100644 --- a/src/rule.cc +++ b/src/rule.cc @@ -651,13 +651,9 @@ bool Rule::evaluate(Transaction *trasn) { if (ret == true) { ruleMessage.m_match = resolveMatchMessage(key, value); for (auto &i : v->m_orign) { - if (ruleMessage.m_reference.empty()) { - ruleMessage.m_reference.append(i->toText()); - } else { - ruleMessage.m_reference.append(";" + i->toText()); - } + ruleMessage.m_reference.append(i->toText()); } - ruleMessage.m_reference.append("-" + *valueTemp.second); + ruleMessage.m_reference.append(*valueTemp.second); updateMatchedVars(trasn, key, value); executeActionsIndependentOfChainedRuleResult(trasn, &containsDisruptive, &ruleMessage); diff --git a/src/transaction.cc b/src/transaction.cc index beae86bf..fc7d18e6 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -105,7 +105,6 @@ Transaction::Transaction(ModSecurity *ms, Rules *rules, void *logCbData) m_serverPort(0), m_uri(""), m_uri_no_query_string_decoded(""), - m_method(""), m_httpVersion(""), m_rules(rules), m_timeStamp(std::time(NULL)), @@ -301,17 +300,20 @@ bool Transaction::addArgument(const std::string& orig, const std::string& key, if (orig == "GET") { m_variableArgsGet.set(key, value, offset); - m_variableArgGetNames.append(key, offset, true); + m_variableArgGetNames.append(key, offset - key.size() - 1, true); } else if (orig == "POST") { m_variableArgsPost.set(key, value, offset); - m_variableArgPostNames.append(key, offset, true); + m_variableArgPostNames.append(key, offset - key.size() - 1, true); } - m_variableArgsNames.append(key, offset, true); + m_variableArgsNames.append(key, offset - key.size() - 1, true); m_ARGScombinedSizeDouble = m_ARGScombinedSizeDouble + \ key.length() + value.length(); - m_variableARGScombinedSize.set(std::to_string(m_ARGScombinedSizeDouble), 0); + m_variableARGScombinedSize.set(std::to_string(m_ARGScombinedSizeDouble), + offset - key.size() - 1, key.size()); + m_variableARGScombinedSize.set(std::to_string(m_ARGScombinedSizeDouble), + offset, value.length()); return true; } @@ -347,7 +349,6 @@ int Transaction::processURI(const char *uri, const char *method, debug(4, "Starting phase URI. (SecRules 0 + 1/2)"); #endif - m_method = method; m_httpVersion = http_version; m_uri = uri; std::string uri_s(uri); @@ -355,10 +356,19 @@ int Transaction::processURI(const char *uri, const char *method, size_t pos = m_uri_decoded.find("?"); size_t pos_raw = uri_s.find("?"); + size_t var_size = pos_raw; - m_variableRequestLine.set(std::string(method) + " " + std::string(uri) + m_variableRequestMethod.set(method, 0); + + + std::string requestLine(std::string(method) + " " + std::string(uri)); + m_variableRequestLine.set(requestLine \ + " HTTP/" + std::string(http_version), m_variableOffset); - m_variableOffset = m_variableRequestLine.m_value.size(); + + m_variableRequestProtocol.set("HTTP/" + std::string(http_version), + m_variableOffset + requestLine.size() + 1); + + if (pos != std::string::npos) { m_uri_no_query_string_decoded = std::string(m_uri_decoded, 0, pos); @@ -366,6 +376,7 @@ int Transaction::processURI(const char *uri, const char *method, m_uri_no_query_string_decoded = std::string(m_uri_decoded); } + if (pos_raw != std::string::npos) { std::string qry = std::string(uri_s, pos_raw + 1, uri_s.length() - (pos_raw + 1)); @@ -379,18 +390,26 @@ int Transaction::processURI(const char *uri, const char *method, } else { path_info = std::string(m_uri_decoded, 0, pos); } - m_variablePathInfo.set(path_info, m_variableOffset); - m_variableRequestFilename.set(path_info, m_variableOffset); + if (var_size == std::string::npos) { + var_size = uri_s.size(); + } + + m_variablePathInfo.set(path_info, m_variableOffset + strlen(method) + + 1, var_size); + m_variableRequestFilename.set(path_info, m_variableOffset + + strlen(method) + 1, var_size); + + size_t offset = path_info.find_last_of("/\\"); if (offset != std::string::npos && path_info.length() > offset + 1) { std::string basename = std::string(path_info, offset + 1, path_info.length() - (offset + 1)); - m_variableRequestBasename.set(basename, m_variableOffset); + m_variableRequestBasename.set(basename, m_variableOffset + + strlen(method) + 1 + offset + 1); } - m_variableRequestMethod.set(method, 0); - m_variableRequestProtocol.set("HTTP/" + std::string(http_version), - m_variableOffset); + + m_variableOffset = m_variableRequestLine.m_value.size(); std::string parsedURI = m_uri_decoded; // The more popular case is without domain @@ -416,8 +435,9 @@ int Transaction::processURI(const char *uri, const char *method, } } - m_variableRequestURI.set(parsedURI, m_variableOffset); - m_variableRequestURIRaw.set(uri, m_variableOffset); + m_variableRequestURI.set(parsedURI, std::string(method).size() + 1, + uri_s.size()); + m_variableRequestURIRaw.set(uri, std::string(method).size() + 1); if (m_variableQueryString.m_value.empty() == false) { extractArguments("GET", m_variableQueryString.m_value, @@ -480,11 +500,11 @@ int Transaction::processRequestHeaders() { */ int Transaction::addRequestHeader(const std::string& key, const std::string& value) { - m_variableRequestHeadersNames.append(key, 0, true); + m_variableRequestHeadersNames.append(key, m_variableOffset, true, + key.size()); m_variableOffset = m_variableOffset + key.size() + 2; m_variableRequestHeaders.set(key, value, m_variableOffset); - m_variableOffset = m_variableOffset + value.size() + 1; std::string keyl = utils::string::tolower(key); @@ -494,19 +514,22 @@ int Transaction::addRequestHeader(const std::string& key, } if (keyl == "cookie") { + size_t localOffset = m_variableOffset; std::vector cookies = utils::string::split(value, ';'); - while (cookies.empty() == false) { - std::vector s = utils::string::split(cookies.back(), + for (const std::string &c : cookies) { + std::vector s = utils::string::split(c, '='); if (s.size() > 1) { if (s[0].at(0) == ' ') { s[0].erase(0, 1); } - m_variableRequestCookies.set(s[0], s[1], m_variableOffset); m_variableRequestCookiesNames.set(s[0], - s[0], m_variableOffset); + s[0], localOffset); + + localOffset = localOffset + s[0].size() + 1; + m_variableRequestCookies.set(s[0], s[1], localOffset); + localOffset = localOffset + s[1].size() + 2; } - cookies.pop_back(); } } /** @@ -534,6 +557,8 @@ int Transaction::addRequestHeader(const std::string& key, std::vector host = utils::string::split(value, ':'); m_variableServerName.set(host[0], m_variableOffset); } + m_variableOffset = m_variableOffset + value.size() + 1; + return 1; } @@ -624,7 +649,7 @@ int Transaction::processRequestBody() { } if (m_variableInboundDataError.m_value.empty() == true) { - m_variableInboundDataError.set("0", m_variableOffset); + m_variableInboundDataError.set("0", 0); } /* @@ -682,7 +707,7 @@ int Transaction::processRequestBody() { if (a != NULL) { Multipart m(*a, this); if (m.init(&error) == true) { - m.process(m_requestBody.str(), &error); + m.process(m_requestBody.str(), &error, m_variableOffset); } m.multipart_complete(&error); } @@ -698,7 +723,8 @@ int Transaction::processRequestBody() { m_variableReqbodyProcessorError.set("0", m_variableOffset); } } else if (m_requestBodyType == WWWFormUrlEncoded) { - extractArguments("POST", m_requestBody.str(), 0); + m_variableOffset++; + extractArguments("POST", m_requestBody.str(), m_variableOffset); } else if (a != NULL) { std::string error; if (a != NULL && a->empty() == false) { @@ -762,7 +788,7 @@ int Transaction::processRequestBody() { m_variableRequestBody.set(m_requestBody.str(), m_variableOffset); m_variableRequestBodyLength.set(std::to_string( m_requestBody.str().size()), - m_variableOffset); + m_variableOffset, m_requestBody.str().size()); } this->m_rules->evaluate(modsecurity::RequestBodyPhase, this); @@ -1310,7 +1336,8 @@ std::string Transaction::toOldAuditLogFormatIndex(const std::string &filename, ss << tstr << " "; ss << "\""; - ss << this->m_method << " "; + ss << utils::string::dash_if_empty(m_variableRequestMethod.evaluate()); + ss << " "; ss << this->m_uri << " "; ss << "HTTP/" << m_httpVersion; ss << "\" "; @@ -1360,7 +1387,9 @@ std::string Transaction::toOldAuditLogFormat(int parts, if (parts & audit_log::AuditLog::BAuditLogPart) { std::vector l; audit_log << "--" << trailer << "-" << "B--" << std::endl; - audit_log << this->m_method << " " << this->m_uri << " " << "HTTP/"; + audit_log << utils::string::dash_if_empty( + m_variableRequestMethod.evaluate()); + audit_log << " " << this->m_uri << " " << "HTTP/"; audit_log << this->m_httpVersion << std::endl; m_variableRequestHeaders.resolve(&l); @@ -1474,7 +1503,10 @@ std::string Transaction::toJSON(int parts) { strlen("request")); yajl_gen_map_open(g); - LOGFY_ADD("protocol", m_method); + LOGFY_ADD("protocol", + utils::string::dash_if_empty( + m_variableRequestMethod.evaluate()).c_str()); + LOGFY_ADD_INT("http_version", m_httpVersion); LOGFY_ADD("uri", this->m_uri); diff --git a/src/variables/remote_user.cc b/src/variables/remote_user.cc index ecb0ae94..9dd83cf9 100644 --- a/src/variables/remote_user.cc +++ b/src/variables/remote_user.cc @@ -41,16 +41,18 @@ void RemoteUser::evaluate(Transaction *transaction, std::vector *l) { size_t pos; std::string base64; + collection::Variable *var; - std::unique_ptr header = std::move( - transaction->m_variableRequestHeaders.resolveFirst("Authorization")); + transaction->m_variableRequestHeaders.resolve("authorization", l); - if (header == NULL) { + if (l->size() < 1) { return; } - if (header->compare(0, 6, "Basic ") == 0) { - base64 = std::string(*header, 6, header->length()); + std::string header(*l->at(0)->m_value); + + if (header.compare(0, 6, "Basic ") == 0) { + base64 = std::string(header, 6, header.length()); } base64 = Utils::Base64::decode(base64); @@ -61,8 +63,18 @@ void RemoteUser::evaluate(Transaction *transaction, } transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos)); - l->push_back(new collection::Variable(&m_retName, - &transaction->m_variableRemoteUser)); + var = new collection::Variable(l->at(0)->m_key, + &transaction->m_variableRemoteUser); + + for (auto &i : l->at(0)->m_orign) { + std::unique_ptr origin(new VariableOrigin()); + origin->m_offset = i->m_offset; + origin->m_length = i->m_length; + var->m_orign.push_back(std::move(origin)); + } + + l->clear(); + l->push_back(var); } diff --git a/test/coding_style_suppressions.txt b/test/coding_style_suppressions.txt index 6ae348a8..e66684e2 100644 --- a/test/coding_style_suppressions.txt +++ b/test/coding_style_suppressions.txt @@ -21,4 +21,12 @@ ./test/fuzzer ./test/libfuzzer ./src/parser/seclang-parser.tab.cc +./src/unique_id.cc:226 +./test/unit/unit.cc:84 +./test/unit/unit.cc:82 +./headers/modsecurity/rule.h:110 +./test/regression/regression.cc:44 +./test/benchmark/owasp-v3/util/av-scanning/runAV/common.h +./src/audit_log/writer/parallel.cc:28 +./src/macro_expansion.c Total errors found diff --git a/test/regression/custom_debug_log.h b/test/regression/custom_debug_log.h index a3ff4b79..defbfdb1 100644 --- a/test/regression/custom_debug_log.h +++ b/test/regression/custom_debug_log.h @@ -31,6 +31,7 @@ class CustomDebugLog : public modsecurity::debug_log::DebugLog { void write(int level, const std::string& message) override; bool contains(const std::string& pattern); std::string log_messages(); + std::string error_log_messages(); private: std::stringstream m_log; diff --git a/test/regression/regression.cc b/test/regression/regression.cc index b749afda..667409cd 100644 --- a/test/regression/regression.cc +++ b/test/regression/regression.cc @@ -475,7 +475,7 @@ int main(int argc, char **argv) { if (r->passed == true && r->skipped == false) { passed++; } else if (r->skipped == false) { - if (test.m_automake_output && 1 == 0) { + if (test.m_automake_output) { // m_automake_output } else { std::cout << KRED << "Test failed." << RESET << KWHT \ diff --git a/test/regression/regression_test.cc b/test/regression/regression_test.cc index 02169e34..81258678 100644 --- a/test/regression/regression_test.cc +++ b/test/regression/regression_test.cc @@ -66,15 +66,15 @@ inline std::vector RegressionTest::yajl_array_to_vec_str( } -inline std::unordered_map +inline std::vector> RegressionTest::yajl_array_to_map(const yajl_val &node) { - std::unordered_map vec; + std::vector> vec; for (int z = 0; z < node->u.object.len; z++) { const char *key = node->u.object.keys[z]; yajl_val val3 = node->u.object.values[z]; const char *value = YAJL_GET_STRING(val3); std::pair a(key, value); - vec.insert(a); + vec.push_back(a); } return vec; } diff --git a/test/regression/regression_test.h b/test/regression/regression_test.h index 3ba30edf..de958df8 100644 --- a/test/regression/regression_test.h +++ b/test/regression/regression_test.h @@ -18,8 +18,10 @@ #include #include #include +#include #include #include +#include #ifndef TEST_REGRESSION_REGRESSION_TEST_H_ #define TEST_REGRESSION_REGRESSION_TEST_H_ @@ -44,8 +46,8 @@ class RegressionTest { int version_max; int github_issue; - std::unordered_map request_headers; - std::unordered_map response_headers; + std::vector> request_headers; + std::vector> response_headers; std::string request_body; std::string response_body; std::string response_protocol; @@ -68,8 +70,8 @@ class RegressionTest { static inline std::string yajl_array_to_str(const yajl_val &node); static inline std::vector yajl_array_to_vec_str( const yajl_val &node); - static inline std::unordered_map yajl_array_to_map(const yajl_val &node); + static inline std::vector> + yajl_array_to_map(const yajl_val &node); int http_code; std::string redirect_url; diff --git a/test/test-cases/regression/offset-variable.json b/test/test-cases/regression/offset-variable.json new file mode 100644 index 00000000..99d8955d --- /dev/null +++ b/test/test-cases/regression/offset-variable.json @@ -0,0 +1,1955 @@ +[ + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - ARGS", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o0,3v23,6t:trim" + }, + "rules":[ + "SecRule ARGS \"@rx val\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - ARGS_GET", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value2", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o3,3v37,6t:trim" + }, + "rules":[ + "SecRule ARGS_GET \"@rx ue2\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - ARGS_POST 1", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1", + "method":"POST", + "body":[ + "param1=value1¶m2=value1" + ] + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o3,3v142,6t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule ARGS_POST \"@rx ue1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - ARGS_POST 2", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1", + "method":"POST", + "body":[ + "param1=value1¶m2=value2¶m3=value3" + ] + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o3,3v156,6t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule ARGS_POST \"@rx ue2\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - ARGS_GET_NAMES 1", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1", + "method":"POST", + "body":[ + "param1=value1¶m2=value2¶m3=value3" + ] + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o0,6v17,6v31,6t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule ARGS_GET_NAMES \"@rx param1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - ARGS_GET_NAMES 2", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1", + "method":"POST", + "body":[ + "param1=value1¶m2=value2¶m3=value3" + ] + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o7,6v17,6v31,6t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule ARGS_GET_NAMES \"@rx param2\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - ARGS_GET_NAMES 3", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1", + "method":"POST", + "body":[ + "param1=value1¶m2=value2¶m3=value3" + ] + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o3,7v17,6v31,6t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule ARGS_GET_NAMES \"@rx am1 par\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - ARGS_GET_NAMES 4", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"POST", + "body":[ + "param1=value1¶m2=value2¶m3=value3" + ] + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o3,14v17,6v31,6v45,6t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule ARGS_GET_NAMES \"@rx am1 param2 par\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - ARGS_POST_NAMES", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"POST", + "body":[ + "param1=value1¶m2=value2¶m3=value3" + ] + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o3,14v149,6v163,6v177,6t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule ARGS_POST_NAMES \"@rx am1 param2 par\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - ARGS_NAMES", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"POST", + "body":[ + "param1=value1¶m2=value2¶m3=value3" + ] + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o0,17v17,6v31,6v45,6v149,6v163,6v177,6t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule ARGS_NAMES \"@rx param1 param2 par\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - ARGS_COMBINED_SIZE 1", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"v16,6v23,6v30,6v37,6v44,6v51,6t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule ARGS_COMBINED_SIZE \"@gt 1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - ARGS_COMBINED_SIZE 2", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"v16,6v23,6v30,6v37,6v44,6v51,6t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule ARGS_COMBINED_SIZE \"@gt 1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - REQUEST_LINE", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded", + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o23,6v0,63t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_LINE \"value1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - REQUEST_METHOD", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded", + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET", + "http_version": 1.1 + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o0,3v0,3t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_METHOD \"GET\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - REQUEST_PROTOCOL", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded", + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET", + "http_version": 1.1 + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o5,3v58,8t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_PROTOCOL \"1.1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - PATH_INFO", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded", + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET", + "http_version": 1.1 + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o1,5v4,11t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule PATH_INFO \"index\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - QUERY_STRING", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded", + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET", + "http_version": 1.1 + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o7,6v16,41t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule QUERY_STRING \"value1\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - REQUEST_BASENAME", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded", + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET", + "http_version": 1.1 + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o6,4v5,10t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_BASENAME \"html\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - REQUEST_URI", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded", + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" + }, + "uri":"/index.html%20%20?param1=value1¶m2=value1¶m3=value1", + "method":"GET", + "http_version": 1.1 + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o7,4v4,59t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_URI \"html\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - REQUEST_URI_RAW", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded", + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" + }, + "uri":"/index.html%20%20?param1=value1¶m2=value1¶m3=value1", + "method":"GET", + "http_version": 1.1 + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o7,4v4,59t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_URI_RAW \"html\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - REQUEST_HEADERS", + "request":{ + "headers":{ + "Content-Length": "27", + "Host":"localhost", + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o0,9v89,9t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_HEADERS \"localhost\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - REQUEST_HEADERS:content-type", + "request":{ + "headers":{ + "Content-Length": "27", + "Host":"localhost", + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o14,3v163,33t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_HEADERS \"www\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - AUTH_TYPE 1", + "request":{ + "headers":{ + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded", + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o0,5v162,5t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule AUTH_TYPE \"Basic\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - AUTH_TYPE 2", + "request":{ + "headers":{ + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o0,5v79,5t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule AUTH_TYPE \"Basic\" \"id:1,phase:2,pass,t:trim,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - REQUEST_HEADERS_NAMES", + "request":{ + "headers":{ + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o0,4v64,13v114,4v130,14v149,12t:lowercase" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_HEADERS_NAMES \"auth\" \"id:1,phase:2,pass,t:lowercase,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - REQUEST_COOKIES 1", + "request":{ + "headers":{ + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded", + "Cookie":"USER_TOKEN=Yes; a=z; t=b" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o1,2v216,3t:lowercase" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_COOKIES \"es\" \"id:1,phase:2,pass,t:lowercase,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - REQUEST_COOKIES 2", + "request":{ + "headers":{ + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded", + "Cookie":"USER_TOKEN=Yes; a=z; t=b" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o0,1v223,1t:lowercase" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_COOKIES \"z\" \"id:1,phase:2,pass,t:lowercase,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - REQUEST_COOKIES 3", + "request":{ + "headers":{ + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded", + "Cookie":"USER_TOKEN=Yes; a=z; t=b" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o0,1v228,1t:lowercase" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_COOKIES \"b\" \"id:1,phase:2,pass,t:lowercase,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - REQUEST_COOKIES_NAMES", + "request":{ + "headers":{ + "AuThOrIzAtIoN": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", + "Host":"localhost", + "Content-Length": "27", + "Content-Type": "application/x-www-form-urlencoded", + "Cookie":"USER_TOKEN=Yes; a=z; t=b" + }, + "uri":"/index.html?param1=value1¶m2=value1¶m3=value1", + "method":"GET" + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "error_log":"o0,1v226,1" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_COOKIES_NAMES \"t\" \"id:1,phase:2,pass,msg:'ops'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: REMOTE_USER", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"27", + "Content-Type":"application/x-www-form-urlencoded", + "Authorization": "Basic QWxhZGRpbjpPcGVuU2VzYW1l" + }, + "uri":"/one/two/three?key1=value1&key2=v%20a%20l%20u%20e%202", + "method":"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":{ + "error_log":"o0,7v198,30t:trim" + }, + "rules":[ + "SecRuleEngine On", + "SecRule REMOTE_USER \"Aladdin\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: REQUEST_BODY", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o45,30v193,516t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_BODY \"Content-Disposition: form-data\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: REQUEST_BODY", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o45,30v193,516t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_BODY \"Content-Disposition: form-data\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: REQUEST_BODY_LENGTH", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"v193,516t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_BODY_LENGTH \"@gt 5\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: REQUEST_FILENAME 1", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/file?something else", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o6,5v5,11t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_FILENAME \"/file\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: REQUEST_FILENAME 2", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20?something else", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o6,8v5,23t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_FILENAME \"/f i l e\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: REQUEST_FILENAME 3", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file.txt\"", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o6,8v5,23t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule REQUEST_FILENAME \"/f i l e\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: ARGS/Multipart 1", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file2.txt\"", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o0,4v306,4t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule ARGS \"test\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Testing Variables :: ARGS/Multipart 2", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name2\"", + "", + "test2", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file2.txt\"", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o0,5v402,5t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule ARGS \"test2\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - FILES", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name2\"", + "", + "test2", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; filename=\"small_text_file2.txt\"; name=\"fiasdfasdfledata\" ", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o0,16v680,20t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule FILES \"small_text_file2\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - FILES", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name2\"", + "", + "test2", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; filename=\"small_text_file2.txt\"; name=\"fiasdfasdfledata\" ", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o0,16v512,20t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule FILES \"small_text_file1\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - FILES_NAMES", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name2\"", + "", + "test2", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; filename=\"small_text_file2.txt\"; name=\"fiasdfasdfledata\" ", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o0,15v512,20t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule FILES_NAMES \"small_text_file\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - FILES_SIZES 1", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name2\"", + "", + "test2", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; filename=\"small_text_file2.txt\"; name=\"fiasdfasdfledata\" ", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"v560,32t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule FILES_SIZES:filedata \"@gt 0\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - FILES_SIZES 2", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name2\"", + "", + "test2", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; filename=\"small_text_file2.txt\"; name=\"fiasdfasdfledata\" ", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"v754,38t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule FILES_SIZES:fiasdfasdfledata \"@gt 0\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - FILES_COMBINED_SIZE", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name2\"", + "", + "test2", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; filename=\"small_text_file2.txt\"; name=\"fiasdfasdfledata\" ", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"v560,32v754,38t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecRule FILES_COMBINED_SIZE \"@gt 0\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - FILES_TMP_CONTENT 1", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name2\"", + "", + "test2", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; filename=\"small_text_file2.txt\"; name=\"fiasdfasdfledata\" ", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o8,7v754,38t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecUploadKeepFiles On", + "SecUploadDir /tmp", + "SecRule FILES_TMP_CONTENT \"another\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - FILES_TMP_CONTENT 2", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name2\"", + "", + "test2", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; filename=\"small_text_file2.txt\"; name=\"fiasdfasdfledata\" ", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o15,5v560,32t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecUploadKeepFiles On", + "SecUploadDir /tmp", + "SecRule FILES_TMP_CONTENT:small_text_file1.txt \"small\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - PATH_INFO", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name2\"", + "", + "test2", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; filename=\"small_text_file2.txt\"; name=\"fiasdfasdfledata\" ", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o6,4v5,23t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecUploadKeepFiles On", + "SecUploadDir /tmp", + "SecRule PATH_INFO \"/f i\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - MULTIPART_FILENAME", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name2\"", + "", + "test2", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; filename=\"small_text_file2.txt\"; name=\"fiasdfasdfledata\" ", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o0,20v680,20t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecUploadKeepFiles On", + "SecUploadDir /tmp", + "SecRule MULTIPART_FILENAME \"small_text_file2.txt\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + }, + { + "enabled":1, + "version_min":300000, + "title":"Variable offset - MULTIPART_NAME", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=--------------------------756b6d74fa1a8ee2", + "Expect":"100-continue" + }, + "uri":"/wheee/f%20i%20l%20e%20", + "method":"POST", + "body":[ + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name\"", + "", + "test", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"name2\"", + "", + "test2", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; name=\"filedata\"; filename=\"small_text_file1.txt\"", + "Content-Type: text/plain", + "", + "This is a very small test file..", + "----------------------------756b6d74fa1a8ee2", + "Content-Disposition: form-data; filename=\"small_text_file2.txt\"; name=\"fiasdfasdfledata\" ", + "Content-Type: text/plain", + "", + "This is another very small test file..", + "----------------------------756b6d74fa1a8ee2--" + ] + }, + "expected":{ + "error_log":"o0,16v709,16t:trim" + }, + "rules":[ + "SecRequestBodyAccess On", + "SecUploadKeepFiles On", + "SecUploadDir /tmp", + "SecRule MULTIPART_NAME \"fiasdfasdfledata\" \"id:1,phase:3,pass,t:trim,msg:'s'\"" + ] + } +] diff --git a/test/test-cases/regression/variable-FILES_NAMES.json b/test/test-cases/regression/variable-FILES_NAMES.json index a77c001e..ef19575d 100644 --- a/test/test-cases/regression/variable-FILES_NAMES.json +++ b/test/test-cases/regression/variable-FILES_NAMES.json @@ -51,7 +51,7 @@ ] }, "expected":{ - "debug_log":"T \\(0\\) t:trim: \"filedata" + "debug_log":"T \\(0\\) t:trim: \"small_text" }, "rules":[ "SecRuleEngine On", diff --git a/test/test-cases/regression/variable-FULL_REQUEST.json b/test/test-cases/regression/variable-FULL_REQUEST.json index 04b1267d..c1fd9711 100644 --- a/test/test-cases/regression/variable-FULL_REQUEST.json +++ b/test/test-cases/regression/variable-FULL_REQUEST.json @@ -51,7 +51,7 @@ ] }, "expected":{ - "debug_log":"Content-Type: multipart/form-data; boundary=------------" + "debug_log":"Multipart: Boundary: --------------------------756b6d74fa1a8ee2" }, "rules":[ "SecRuleEngine On", diff --git a/test/test-cases/regression/variable-RESPONSE_HEADERS_NAMES.json b/test/test-cases/regression/variable-RESPONSE_HEADERS_NAMES.json index 68be5d57..69accf11 100644 --- a/test/test-cases/regression/variable-RESPONSE_HEADERS_NAMES.json +++ b/test/test-cases/regression/variable-RESPONSE_HEADERS_NAMES.json @@ -51,7 +51,7 @@ ] }, "expected":{ - "debug_log":"Target value: \"Content-Type Last-Modified Date\" \\(Variable: RESPONSE_HEADERS_NAMES\\)" + "debug_log":"Target value: \"Date Last-Modified Content-Type\" \\(Variable: RESPONSE_HEADERS_NAMES\\)" }, "rules":[ "SecRuleEngine On", diff --git a/test/unit/unit.cc b/test/unit/unit.cc index 96df4cd4..2d8673da 100644 --- a/test/unit/unit.cc +++ b/test/unit/unit.cc @@ -240,7 +240,7 @@ int main(int argc, char **argv) { } else { for (auto &i : r) { if (i->skipped == true) { - skp++; + skp++; } } std::cout << KRED << r.size()-skp << " tests failed."; @@ -275,7 +275,7 @@ int main(int argc, char **argv) { int skp = 0; for (auto &i : results) { if (i->skipped == true) { - skp++; + skp++; } } std::cout << KRED << results.size()-skp << " failed.";