mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 13:56:01 +03:00
Adds offset regression tests and assorted fixes on var's offsets
This commit is contained in:
parent
795994bb0e
commit
4ad3574cf2
@ -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/strmatch.json
|
||||||
TESTS+=test/test-cases/secrules-language-tests/operators/detectXSS.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/secrules-language-tests/operators/eq.json
|
||||||
|
TESTS+=test/test-cases/regression/offset-variable.json
|
||||||
|
|
||||||
|
@ -75,6 +75,10 @@ class AnchoredSetVariable : public std::unordered_multimap<std::string,
|
|||||||
|
|
||||||
void set(const std::string &key, const std::string &value,
|
void set(const std::string &key, const std::string &value,
|
||||||
size_t offset);
|
size_t offset);
|
||||||
|
|
||||||
|
void set(const std::string &key, const std::string &value,
|
||||||
|
size_t offset, size_t len);
|
||||||
|
|
||||||
void setCopy(std::string key, std::string value, size_t offset);
|
void setCopy(std::string key, std::string value, size_t offset);
|
||||||
|
|
||||||
void resolve(std::vector<const collection::Variable *> *l);
|
void resolve(std::vector<const collection::Variable *> *l);
|
||||||
|
@ -47,8 +47,12 @@ class AnchoredVariable {
|
|||||||
|
|
||||||
void unset();
|
void unset();
|
||||||
void set(const std::string &a, size_t offset);
|
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,
|
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<const collection::Variable *> *l);
|
void evaluate(std::vector<const collection::Variable *> *l);
|
||||||
std::string * evaluate();
|
std::string * evaluate();
|
||||||
std::unique_ptr<std::string> resolveFirst();
|
std::unique_ptr<std::string> resolveFirst();
|
||||||
|
@ -352,11 +352,6 @@ class Transaction : public TransactionAnchoredVariables {
|
|||||||
*/
|
*/
|
||||||
const char *m_httpVersion;
|
const char *m_httpVersion;
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds the request method: GET, POST, HEAD ...
|
|
||||||
*/
|
|
||||||
const char *m_method;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the server IP Address
|
* Holds the server IP Address
|
||||||
*/
|
*/
|
||||||
|
@ -40,7 +40,7 @@ class VariableOrigin {
|
|||||||
std::string toText() {
|
std::string toText() {
|
||||||
std::string offset = std::to_string(m_offset);
|
std::string offset = std::to_string(m_offset);
|
||||||
std::string len = std::to_string(m_length);
|
std::string len = std::to_string(m_length);
|
||||||
return "rr:" + offset + "," + len;
|
return "v" + offset + "," + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int m_length;
|
int m_length;
|
||||||
|
@ -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<VariableOrigin> 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,
|
void AnchoredSetVariable::set(const std::string &key,
|
||||||
const std::string &value, size_t offset) {
|
const std::string &value, size_t offset) {
|
||||||
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
|
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
|
||||||
|
@ -56,6 +56,18 @@ void AnchoredVariable::unset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AnchoredVariable::set(const std::string &a, size_t offset,
|
||||||
|
size_t offsetLen) {
|
||||||
|
std::unique_ptr<VariableOrigin> 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) {
|
void AnchoredVariable::set(const std::string &a, size_t offset) {
|
||||||
std::unique_ptr<VariableOrigin> origin(new VariableOrigin());
|
std::unique_ptr<VariableOrigin> 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<VariableOrigin> 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<const collection::Variable *> *l) {
|
void AnchoredVariable::evaluate(std::vector<const collection::Variable *> *l) {
|
||||||
if (m_name.empty() || m_var == NULL || m_var->m_key == NULL
|
if (m_name.empty() || m_var == NULL || m_var->m_key == NULL
|
||||||
|| m_var->m_value == NULL || m_var->m_key->empty()) {
|
|| m_var->m_value == NULL || m_var->m_key->empty()) {
|
||||||
|
@ -144,7 +144,7 @@ bool Parallel::write(Transaction *transaction, int parts, std::string *error) {
|
|||||||
|
|
||||||
std::ofstream myfile;
|
std::ofstream myfile;
|
||||||
std::string a(fileName.c_str());
|
std::string a(fileName.c_str());
|
||||||
myfile.open (a);
|
myfile.open(a);
|
||||||
myfile << log;
|
myfile << log;
|
||||||
myfile.close();
|
myfile.close();
|
||||||
|
|
||||||
|
@ -78,10 +78,7 @@ class Operator {
|
|||||||
|
|
||||||
static void logOffset(RuleMessage *ruleMessage, int offset, int len) {
|
static void logOffset(RuleMessage *ruleMessage, int offset, int len) {
|
||||||
if (ruleMessage) {
|
if (ruleMessage) {
|
||||||
if (ruleMessage->m_reference.empty() == false) {
|
ruleMessage->m_reference.append("o"
|
||||||
ruleMessage->m_reference.append(";");
|
|
||||||
}
|
|
||||||
ruleMessage->m_reference.append("op:"
|
|
||||||
+ std::to_string(offset) + ","
|
+ std::to_string(offset) + ","
|
||||||
+ std::to_string(len));
|
+ std::to_string(len));
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_REQUEST_BODY_PROCESSOR_JSON_H_
|
||||||
|
#define SRC_REQUEST_BODY_PROCESSOR_JSON_H_
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_YAJL
|
#ifdef WITH_YAJL
|
||||||
|
|
||||||
@ -24,8 +27,6 @@
|
|||||||
#include "modsecurity/transaction.h"
|
#include "modsecurity/transaction.h"
|
||||||
#include "modsecurity/rules.h"
|
#include "modsecurity/rules.h"
|
||||||
|
|
||||||
#ifndef SRC_REQUEST_BODY_PROCESSOR_JSON_H_
|
|
||||||
#define SRC_REQUEST_BODY_PROCESSOR_JSON_H_
|
|
||||||
|
|
||||||
|
|
||||||
namespace modsecurity {
|
namespace modsecurity {
|
||||||
@ -82,7 +83,6 @@ class JSON {
|
|||||||
} // namespace RequestBodyProcessor
|
} // namespace RequestBodyProcessor
|
||||||
} // namespace modsecurity
|
} // namespace modsecurity
|
||||||
|
|
||||||
|
#endif // WITH_YAJL
|
||||||
|
|
||||||
#endif // SRC_REQUEST_BODY_PROCESSOR_JSON_H_
|
#endif // SRC_REQUEST_BODY_PROCESSOR_JSON_H_
|
||||||
|
|
||||||
#endif // WITH_YAJL
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "modsecurity/collection/collections.h"
|
#include "modsecurity/collection/collections.h"
|
||||||
#include "modsecurity/rules.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;
|
const char *p = NULL;
|
||||||
|
|
||||||
/* accept only what we understand */
|
/* accept only what we understand */
|
||||||
@ -342,7 +343,8 @@ int Multipart::parse_content_disposition(const char *c_d_value) {
|
|||||||
if (name == "name") {
|
if (name == "name") {
|
||||||
validate_quotes(value.c_str());
|
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()) {
|
if (!m_mpp->m_name.empty()) {
|
||||||
debug(4, "Multipart: Warning: Duplicate Content-Disposition " \
|
debug(4, "Multipart: Warning: Duplicate Content-Disposition " \
|
||||||
@ -350,10 +352,12 @@ int Multipart::parse_content_disposition(const char *c_d_value) {
|
|||||||
return -14;
|
return -14;
|
||||||
}
|
}
|
||||||
m_mpp->m_name.assign(value);
|
m_mpp->m_name.assign(value);
|
||||||
|
m_mpp->m_nameOffset = offset + ((p - c_d_value) - value.size());
|
||||||
debug(9, "Multipart: Content-Disposition name: " + value + ".");
|
debug(9, "Multipart: Content-Disposition name: " + value + ".");
|
||||||
} else if (name == "filename") {
|
} else if (name == "filename") {
|
||||||
validate_quotes(value.c_str());
|
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()) {
|
if (!m_mpp->m_filename.empty()) {
|
||||||
debug(4, "Multipart: Warning: Duplicate Content-Disposition " \
|
debug(4, "Multipart: Warning: Duplicate Content-Disposition " \
|
||||||
@ -361,6 +365,7 @@ int Multipart::parse_content_disposition(const char *c_d_value) {
|
|||||||
return -15;
|
return -15;
|
||||||
}
|
}
|
||||||
m_mpp->m_filename.assign(value);
|
m_mpp->m_filename.assign(value);
|
||||||
|
m_mpp->m_filenameOffset = offset + ((p - c_d_value) - value.size());
|
||||||
|
|
||||||
debug(9, "Multipart: Content-Disposition filename: " \
|
debug(9, "Multipart: Content-Disposition filename: " \
|
||||||
+ value + ".");
|
+ 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 *p = m_buf + (MULTIPART_BUF_SIZE - m_bufleft);
|
||||||
char localreserve[2] = { '\0', '\0' }; /* initialized to quiet warning */
|
char localreserve[2] = { '\0', '\0' }; /* initialized to quiet warning */
|
||||||
int bytes_reserved = 0;
|
int bytes_reserved = 0;
|
||||||
@ -525,7 +530,11 @@ int Multipart::process_part_data(std::string *error) {
|
|||||||
return -1;
|
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];
|
m_mpp->m_length += m_reserve[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,12 +550,26 @@ int Multipart::process_part_data(std::string *error) {
|
|||||||
return -1;
|
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);
|
m_mpp->m_length += (MULTIPART_BUF_SIZE - m_bufleft);
|
||||||
} else {
|
} else {
|
||||||
/* just keep track of the file size */
|
/* 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];
|
+ 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];
|
m_mpp->m_length += (MULTIPART_BUF_SIZE - m_bufleft) + m_reserve[0];
|
||||||
}
|
}
|
||||||
} else if (m_mpp->m_type == MULTIPART_FORMDATA) {
|
} 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_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);
|
debug(9, "Multipart: Added data to variable: " + d);
|
||||||
} else {
|
} 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;
|
int i, len;
|
||||||
|
|
||||||
/* Check for nul bytes. */
|
/* 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. */
|
/* The buffer is data so increase the data length counter. */
|
||||||
m_reqbody_no_files_length += (MULTIPART_BUF_SIZE - m_bufleft);
|
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.");
|
"Content-Disposition header.");
|
||||||
return false;
|
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) {
|
if (rc < 0) {
|
||||||
debug(1, "Multipart: Invalid Content-Disposition header ("
|
debug(1, "Multipart: Invalid Content-Disposition header ("
|
||||||
+ std::to_string(rc) + "): " + header_value);
|
+ std::to_string(rc) + "): " + header_value);
|
||||||
@ -714,15 +739,17 @@ int Multipart::process_part_header(std::string *error) {
|
|||||||
m_flag_invalid_header_folding = 1;
|
m_flag_invalid_header_folding = 1;
|
||||||
}
|
}
|
||||||
data++;
|
data++;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_value = std::string(data);
|
new_value = std::string(data);
|
||||||
utils::string::chomp(&new_value);
|
utils::string::chomp(&new_value);
|
||||||
|
|
||||||
/* update the header value in the table */
|
/* 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;
|
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 \"" \
|
debug(9, "Multipart: Continued folder header \"" \
|
||||||
+ m_mpp->m_last_header_name + "\" with \"" \
|
+ m_mpp->m_last_header_name + "\" with \"" \
|
||||||
@ -742,6 +769,7 @@ int Multipart::process_part_header(std::string *error) {
|
|||||||
data = m_buf;
|
data = m_buf;
|
||||||
while ((*data != ':') && (*data != '\0')) {
|
while ((*data != ':') && (*data != '\0')) {
|
||||||
data++;
|
data++;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
if (*data == '\0') {
|
if (*data == '\0') {
|
||||||
debug(1, "Multipart: Invalid part header (colon missing): " \
|
debug(1, "Multipart: Invalid part header (colon missing): " \
|
||||||
@ -763,8 +791,10 @@ int Multipart::process_part_header(std::string *error) {
|
|||||||
|
|
||||||
/* extract the value value */
|
/* extract the value value */
|
||||||
data++;
|
data++;
|
||||||
|
i++;
|
||||||
while ((*data == '\t') || (*data == ' ')) {
|
while ((*data == '\t') || (*data == ' ')) {
|
||||||
data++;
|
data++;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
header_value = std::string(data);
|
header_value = std::string(data);
|
||||||
utils::string::chomp(&header_value);
|
utils::string::chomp(&header_value);
|
||||||
@ -780,7 +810,8 @@ int Multipart::process_part_header(std::string *error) {
|
|||||||
|
|
||||||
|
|
||||||
m_mpp->m_headers.emplace(
|
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 \
|
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) {
|
if (m_mpp->m_type != MULTIPART_FILE) {
|
||||||
/* now construct a single string out of the parts */
|
/* now construct a single string out of the parts */
|
||||||
for (std::string &i : m_mpp->m_value_parts) {
|
for (const auto &i : m_mpp->m_value_parts) {
|
||||||
m_mpp->m_value.append(i);
|
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()) {
|
if (m->m_name.empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
size_t offset = m_transaction->m_variableOffset + 1;
|
||||||
|
|
||||||
if (m->m_type == MULTIPART_FILE) {
|
if (m->m_type == MULTIPART_FILE) {
|
||||||
std::string tmp_name;
|
std::string tmp_name;
|
||||||
@ -996,25 +1031,36 @@ int Multipart::multipart_complete(std::string *error) {
|
|||||||
if (!m->m_filename.empty()) {
|
if (!m->m_filename.empty()) {
|
||||||
name.assign(m->m_filename);
|
name.assign(m->m_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_transaction->m_variableFiles.set(m->m_filename,
|
m_transaction->m_variableFiles.set(m->m_filename,
|
||||||
m->m_filename, 0);
|
m->m_filename, m->m_filenameOffset);
|
||||||
m_transaction->m_variableFilesNames.set(m->m_name,
|
|
||||||
m->m_name, 0);
|
m_transaction->m_variableFilesNames.set(m->m_filename,
|
||||||
|
m->m_filename, m->m_filenameOffset);
|
||||||
|
|
||||||
m_transaction->m_variableFilesSizes.set(m->m_name,
|
m_transaction->m_variableFilesSizes.set(m->m_name,
|
||||||
std::to_string(m->m_tmp_file_size), 0);
|
std::to_string(m->m_tmp_file_size.first),
|
||||||
m_transaction->m_variableFilesTmpContent.set(m->m_name,
|
m->m_tmp_file_size.second,
|
||||||
m->m_value, 0);
|
m->m_tmp_file_size.first);
|
||||||
m_transaction->m_variableFilesTmpContent.set(m->m_name,
|
|
||||||
m->m_value, 0);
|
m_transaction->m_variableFilesTmpContent.set(m->m_filename,
|
||||||
m_transaction->m_variableFilesTmpNames.set(m->m_name,
|
m->m_value, m->m_valueOffset);
|
||||||
m->m_value, 0);
|
|
||||||
file_combined_size = file_combined_size + m->m_tmp_file_size;
|
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 {
|
} else {
|
||||||
debug(4, "Adding request argument (BODY): name \"" +
|
debug(4, "Adding request argument (BODY): name \"" +
|
||||||
m->m_name + "\", value \"" + m->m_value + "\"");
|
m->m_name + "\", value \"" + m->m_value + "\"");
|
||||||
m_transaction->m_variableArgs.set(m->m_name, m->m_value,
|
m_transaction->m_variableArgs.set(m->m_name, m->m_value,
|
||||||
m_transaction->m_variableOffset);
|
offset + m->m_valueOffset);
|
||||||
m_transaction->m_variableArgsPost.set(m->m_name, m->m_value, 0);
|
m_transaction->m_variableArgsPost.set(m->m_name, m->m_value,
|
||||||
|
offset + m->m_valueOffset);
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
if (m_transaction->m_namesArgs->empty()) {
|
if (m_transaction->m_namesArgs->empty()) {
|
||||||
@ -1036,9 +1082,7 @@ int Multipart::multipart_complete(std::string *error) {
|
|||||||
std::to_string(m_transaction->->m_ARGScombinedSize));
|
std::to_string(m_transaction->->m_ARGScombinedSize));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
m_transaction->m_variableFilesCombinedSize.set(
|
|
||||||
std::to_string(file_combined_size),
|
|
||||||
m_transaction->m_variableOffset);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1256,12 +1300,13 @@ bool Multipart::init(std::string *error) {
|
|||||||
* Assuming that all data is on data. We are not processing chunks.
|
* 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();
|
const char *inptr = data.c_str();
|
||||||
unsigned int inleft = data.size();
|
unsigned int inleft = data.size();
|
||||||
|
size_t z = 0;
|
||||||
|
|
||||||
if (data.size() == 0) return true;
|
if (data.size() == 0) return true;
|
||||||
|
|
||||||
m_seen_data = true;
|
m_seen_data = true;
|
||||||
|
|
||||||
if (m_is_complete) {
|
if (m_is_complete) {
|
||||||
@ -1285,6 +1330,8 @@ bool Multipart::process(const std::string& data, std::string *error) {
|
|||||||
char c = *inptr;
|
char c = *inptr;
|
||||||
int process_buffer = 0;
|
int process_buffer = 0;
|
||||||
|
|
||||||
|
z++;
|
||||||
|
|
||||||
if ((c == '\r') && (m_bufleft == 1)) {
|
if ((c == '\r') && (m_bufleft == 1)) {
|
||||||
/* we don't want to take \r as the last byte in the buffer */
|
/* we don't want to take \r as the last byte in the buffer */
|
||||||
process_buffer = 1;
|
process_buffer = 1;
|
||||||
@ -1443,13 +1490,13 @@ bool Multipart::process(const std::string& data, std::string *error) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process_part_header(error) < 0) {
|
if (process_part_header(error, offset + z) < 0) {
|
||||||
m_flag_error = 1;
|
m_flag_error = 1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (process_part_data(error) < 0) {
|
if (process_part_data(error, offset + z) < 0) {
|
||||||
m_flag_error = 1;
|
m_flag_error = 1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#ifndef SRC_REQUEST_BODY_PROCESSOR_MULTIPART_H_
|
#ifndef SRC_REQUEST_BODY_PROCESSOR_MULTIPART_H_
|
||||||
#define SRC_REQUEST_BODY_PROCESSOR_MULTIPART_H_
|
#define SRC_REQUEST_BODY_PROCESSOR_MULTIPART_H_
|
||||||
@ -58,9 +59,14 @@ class MultipartPart {
|
|||||||
MultipartPart()
|
MultipartPart()
|
||||||
: m_type(MULTIPART_FORMDATA),
|
: m_type(MULTIPART_FORMDATA),
|
||||||
m_tmp_file_fd(0),
|
m_tmp_file_fd(0),
|
||||||
m_tmp_file_size(0),
|
|
||||||
m_offset(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() {
|
~MultipartPart() {
|
||||||
m_headers.clear();
|
m_headers.clear();
|
||||||
@ -72,10 +78,13 @@ class MultipartPart {
|
|||||||
|
|
||||||
/* the name */
|
/* the name */
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
size_t m_nameOffset;
|
||||||
|
|
||||||
/* variables only, variable value */
|
/* variables only, variable value */
|
||||||
std::string m_value;
|
std::string m_value;
|
||||||
std::list<std::string> m_value_parts;
|
size_t m_valueOffset;
|
||||||
|
|
||||||
|
std::list<std::pair<std::string, int>> m_value_parts;
|
||||||
|
|
||||||
/* files only, the content type (where available) */
|
/* files only, the content type (where available) */
|
||||||
/* std::string m_content_type; */
|
/* std::string m_content_type; */
|
||||||
@ -83,13 +92,15 @@ class MultipartPart {
|
|||||||
/* files only, the name of the temporary file holding data */
|
/* files only, the name of the temporary file holding data */
|
||||||
std::string m_tmp_file_name;
|
std::string m_tmp_file_name;
|
||||||
int m_tmp_file_fd;
|
int m_tmp_file_fd;
|
||||||
unsigned int m_tmp_file_size;
|
std::pair<size_t, size_t> m_tmp_file_size;
|
||||||
|
|
||||||
/* files only, filename as supplied by the browser */
|
/* files only, filename as supplied by the browser */
|
||||||
std::string m_filename;
|
std::string m_filename;
|
||||||
|
size_t m_filenameOffset;
|
||||||
|
|
||||||
std::string m_last_header_name;
|
std::string m_last_header_name;
|
||||||
std::unordered_map<std::string, std::string, MyHash, MyEqual> m_headers;
|
std::unordered_map<std::string, std::pair<size_t, std::string>,
|
||||||
|
MyHash, MyEqual> m_headers;
|
||||||
|
|
||||||
unsigned int m_offset;
|
unsigned int m_offset;
|
||||||
unsigned int m_length;
|
unsigned int m_length;
|
||||||
@ -108,11 +119,11 @@ class Multipart {
|
|||||||
int is_token_char(unsigned char c);
|
int is_token_char(unsigned char c);
|
||||||
int multipart_complete(std::string *err);
|
int multipart_complete(std::string *err);
|
||||||
|
|
||||||
int parse_content_disposition(const char *c_d_value);
|
int parse_content_disposition(const char *c_d_value, int offset);
|
||||||
bool process(const std::string& data, std::string *err);
|
bool process(const std::string& data, std::string *err, int offset);
|
||||||
int process_boundary(int last_part);
|
int process_boundary(int last_part);
|
||||||
int process_part_header(std::string *error);
|
int process_part_header(std::string *error, int offset);
|
||||||
int process_part_data(std::string *error);
|
int process_part_data(std::string *error, size_t offset);
|
||||||
|
|
||||||
int tmp_file_name(std::string *filename) const;
|
int tmp_file_name(std::string *filename) const;
|
||||||
|
|
||||||
|
@ -651,13 +651,9 @@ bool Rule::evaluate(Transaction *trasn) {
|
|||||||
if (ret == true) {
|
if (ret == true) {
|
||||||
ruleMessage.m_match = resolveMatchMessage(key, value);
|
ruleMessage.m_match = resolveMatchMessage(key, value);
|
||||||
for (auto &i : v->m_orign) {
|
for (auto &i : v->m_orign) {
|
||||||
if (ruleMessage.m_reference.empty()) {
|
ruleMessage.m_reference.append(i->toText());
|
||||||
ruleMessage.m_reference.append(i->toText());
|
|
||||||
} else {
|
|
||||||
ruleMessage.m_reference.append(";" + i->toText());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ruleMessage.m_reference.append("-" + *valueTemp.second);
|
ruleMessage.m_reference.append(*valueTemp.second);
|
||||||
updateMatchedVars(trasn, key, value);
|
updateMatchedVars(trasn, key, value);
|
||||||
executeActionsIndependentOfChainedRuleResult(trasn,
|
executeActionsIndependentOfChainedRuleResult(trasn,
|
||||||
&containsDisruptive, &ruleMessage);
|
&containsDisruptive, &ruleMessage);
|
||||||
|
@ -105,7 +105,6 @@ Transaction::Transaction(ModSecurity *ms, Rules *rules, void *logCbData)
|
|||||||
m_serverPort(0),
|
m_serverPort(0),
|
||||||
m_uri(""),
|
m_uri(""),
|
||||||
m_uri_no_query_string_decoded(""),
|
m_uri_no_query_string_decoded(""),
|
||||||
m_method(""),
|
|
||||||
m_httpVersion(""),
|
m_httpVersion(""),
|
||||||
m_rules(rules),
|
m_rules(rules),
|
||||||
m_timeStamp(std::time(NULL)),
|
m_timeStamp(std::time(NULL)),
|
||||||
@ -301,17 +300,20 @@ bool Transaction::addArgument(const std::string& orig, const std::string& key,
|
|||||||
|
|
||||||
if (orig == "GET") {
|
if (orig == "GET") {
|
||||||
m_variableArgsGet.set(key, value, offset);
|
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") {
|
} else if (orig == "POST") {
|
||||||
m_variableArgsPost.set(key, value, offset);
|
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 + \
|
m_ARGScombinedSizeDouble = m_ARGScombinedSizeDouble + \
|
||||||
key.length() + value.length();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -347,7 +349,6 @@ int Transaction::processURI(const char *uri, const char *method,
|
|||||||
debug(4, "Starting phase URI. (SecRules 0 + 1/2)");
|
debug(4, "Starting phase URI. (SecRules 0 + 1/2)");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_method = method;
|
|
||||||
m_httpVersion = http_version;
|
m_httpVersion = http_version;
|
||||||
m_uri = uri;
|
m_uri = uri;
|
||||||
std::string uri_s(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 = m_uri_decoded.find("?");
|
||||||
size_t pos_raw = uri_s.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);
|
+ " 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) {
|
if (pos != std::string::npos) {
|
||||||
m_uri_no_query_string_decoded = std::string(m_uri_decoded, 0, pos);
|
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);
|
m_uri_no_query_string_decoded = std::string(m_uri_decoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (pos_raw != std::string::npos) {
|
if (pos_raw != std::string::npos) {
|
||||||
std::string qry = std::string(uri_s, pos_raw + 1,
|
std::string qry = std::string(uri_s, pos_raw + 1,
|
||||||
uri_s.length() - (pos_raw + 1));
|
uri_s.length() - (pos_raw + 1));
|
||||||
@ -379,18 +390,26 @@ int Transaction::processURI(const char *uri, const char *method,
|
|||||||
} else {
|
} else {
|
||||||
path_info = std::string(m_uri_decoded, 0, pos);
|
path_info = std::string(m_uri_decoded, 0, pos);
|
||||||
}
|
}
|
||||||
m_variablePathInfo.set(path_info, m_variableOffset);
|
if (var_size == std::string::npos) {
|
||||||
m_variableRequestFilename.set(path_info, m_variableOffset);
|
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("/\\");
|
size_t offset = path_info.find_last_of("/\\");
|
||||||
if (offset != std::string::npos && path_info.length() > offset + 1) {
|
if (offset != std::string::npos && path_info.length() > offset + 1) {
|
||||||
std::string basename = std::string(path_info, offset + 1,
|
std::string basename = std::string(path_info, offset + 1,
|
||||||
path_info.length() - (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_variableRequestLine.m_value.size();
|
||||||
m_variableOffset);
|
|
||||||
|
|
||||||
std::string parsedURI = m_uri_decoded;
|
std::string parsedURI = m_uri_decoded;
|
||||||
// The more popular case is without domain
|
// 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_variableRequestURI.set(parsedURI, std::string(method).size() + 1,
|
||||||
m_variableRequestURIRaw.set(uri, m_variableOffset);
|
uri_s.size());
|
||||||
|
m_variableRequestURIRaw.set(uri, std::string(method).size() + 1);
|
||||||
|
|
||||||
if (m_variableQueryString.m_value.empty() == false) {
|
if (m_variableQueryString.m_value.empty() == false) {
|
||||||
extractArguments("GET", m_variableQueryString.m_value,
|
extractArguments("GET", m_variableQueryString.m_value,
|
||||||
@ -480,11 +500,11 @@ int Transaction::processRequestHeaders() {
|
|||||||
*/
|
*/
|
||||||
int Transaction::addRequestHeader(const std::string& key,
|
int Transaction::addRequestHeader(const std::string& key,
|
||||||
const std::string& value) {
|
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_variableOffset = m_variableOffset + key.size() + 2;
|
||||||
m_variableRequestHeaders.set(key, value, m_variableOffset);
|
m_variableRequestHeaders.set(key, value, m_variableOffset);
|
||||||
m_variableOffset = m_variableOffset + value.size() + 1;
|
|
||||||
|
|
||||||
|
|
||||||
std::string keyl = utils::string::tolower(key);
|
std::string keyl = utils::string::tolower(key);
|
||||||
@ -494,19 +514,22 @@ int Transaction::addRequestHeader(const std::string& key,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (keyl == "cookie") {
|
if (keyl == "cookie") {
|
||||||
|
size_t localOffset = m_variableOffset;
|
||||||
std::vector<std::string> cookies = utils::string::split(value, ';');
|
std::vector<std::string> cookies = utils::string::split(value, ';');
|
||||||
while (cookies.empty() == false) {
|
for (const std::string &c : cookies) {
|
||||||
std::vector<std::string> s = utils::string::split(cookies.back(),
|
std::vector<std::string> s = utils::string::split(c,
|
||||||
'=');
|
'=');
|
||||||
if (s.size() > 1) {
|
if (s.size() > 1) {
|
||||||
if (s[0].at(0) == ' ') {
|
if (s[0].at(0) == ' ') {
|
||||||
s[0].erase(0, 1);
|
s[0].erase(0, 1);
|
||||||
}
|
}
|
||||||
m_variableRequestCookies.set(s[0], s[1], m_variableOffset);
|
|
||||||
m_variableRequestCookiesNames.set(s[0],
|
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<std::string> host = utils::string::split(value, ':');
|
std::vector<std::string> host = utils::string::split(value, ':');
|
||||||
m_variableServerName.set(host[0], m_variableOffset);
|
m_variableServerName.set(host[0], m_variableOffset);
|
||||||
}
|
}
|
||||||
|
m_variableOffset = m_variableOffset + value.size() + 1;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -624,7 +649,7 @@ int Transaction::processRequestBody() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_variableInboundDataError.m_value.empty() == true) {
|
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) {
|
if (a != NULL) {
|
||||||
Multipart m(*a, this);
|
Multipart m(*a, this);
|
||||||
if (m.init(&error) == true) {
|
if (m.init(&error) == true) {
|
||||||
m.process(m_requestBody.str(), &error);
|
m.process(m_requestBody.str(), &error, m_variableOffset);
|
||||||
}
|
}
|
||||||
m.multipart_complete(&error);
|
m.multipart_complete(&error);
|
||||||
}
|
}
|
||||||
@ -698,7 +723,8 @@ int Transaction::processRequestBody() {
|
|||||||
m_variableReqbodyProcessorError.set("0", m_variableOffset);
|
m_variableReqbodyProcessorError.set("0", m_variableOffset);
|
||||||
}
|
}
|
||||||
} else if (m_requestBodyType == WWWFormUrlEncoded) {
|
} else if (m_requestBodyType == WWWFormUrlEncoded) {
|
||||||
extractArguments("POST", m_requestBody.str(), 0);
|
m_variableOffset++;
|
||||||
|
extractArguments("POST", m_requestBody.str(), m_variableOffset);
|
||||||
} else if (a != NULL) {
|
} else if (a != NULL) {
|
||||||
std::string error;
|
std::string error;
|
||||||
if (a != NULL && a->empty() == false) {
|
if (a != NULL && a->empty() == false) {
|
||||||
@ -762,7 +788,7 @@ int Transaction::processRequestBody() {
|
|||||||
m_variableRequestBody.set(m_requestBody.str(), m_variableOffset);
|
m_variableRequestBody.set(m_requestBody.str(), m_variableOffset);
|
||||||
m_variableRequestBodyLength.set(std::to_string(
|
m_variableRequestBodyLength.set(std::to_string(
|
||||||
m_requestBody.str().size()),
|
m_requestBody.str().size()),
|
||||||
m_variableOffset);
|
m_variableOffset, m_requestBody.str().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
this->m_rules->evaluate(modsecurity::RequestBodyPhase, this);
|
this->m_rules->evaluate(modsecurity::RequestBodyPhase, this);
|
||||||
@ -1310,7 +1336,8 @@ std::string Transaction::toOldAuditLogFormatIndex(const std::string &filename,
|
|||||||
ss << tstr << " ";
|
ss << tstr << " ";
|
||||||
|
|
||||||
ss << "\"";
|
ss << "\"";
|
||||||
ss << this->m_method << " ";
|
ss << utils::string::dash_if_empty(m_variableRequestMethod.evaluate());
|
||||||
|
ss << " ";
|
||||||
ss << this->m_uri << " ";
|
ss << this->m_uri << " ";
|
||||||
ss << "HTTP/" << m_httpVersion;
|
ss << "HTTP/" << m_httpVersion;
|
||||||
ss << "\" ";
|
ss << "\" ";
|
||||||
@ -1360,7 +1387,9 @@ std::string Transaction::toOldAuditLogFormat(int parts,
|
|||||||
if (parts & audit_log::AuditLog::BAuditLogPart) {
|
if (parts & audit_log::AuditLog::BAuditLogPart) {
|
||||||
std::vector<const collection::Variable *> l;
|
std::vector<const collection::Variable *> l;
|
||||||
audit_log << "--" << trailer << "-" << "B--" << std::endl;
|
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;
|
audit_log << this->m_httpVersion << std::endl;
|
||||||
|
|
||||||
m_variableRequestHeaders.resolve(&l);
|
m_variableRequestHeaders.resolve(&l);
|
||||||
@ -1474,7 +1503,10 @@ std::string Transaction::toJSON(int parts) {
|
|||||||
strlen("request"));
|
strlen("request"));
|
||||||
yajl_gen_map_open(g);
|
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_INT("http_version", m_httpVersion);
|
||||||
LOGFY_ADD("uri", this->m_uri);
|
LOGFY_ADD("uri", this->m_uri);
|
||||||
|
|
||||||
|
@ -41,16 +41,18 @@ void RemoteUser::evaluate(Transaction *transaction,
|
|||||||
std::vector<const collection::Variable *> *l) {
|
std::vector<const collection::Variable *> *l) {
|
||||||
size_t pos;
|
size_t pos;
|
||||||
std::string base64;
|
std::string base64;
|
||||||
|
collection::Variable *var;
|
||||||
|
|
||||||
std::unique_ptr<std::string> header = std::move(
|
transaction->m_variableRequestHeaders.resolve("authorization", l);
|
||||||
transaction->m_variableRequestHeaders.resolveFirst("Authorization"));
|
|
||||||
|
|
||||||
if (header == NULL) {
|
if (l->size() < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header->compare(0, 6, "Basic ") == 0) {
|
std::string header(*l->at(0)->m_value);
|
||||||
base64 = std::string(*header, 6, header->length());
|
|
||||||
|
if (header.compare(0, 6, "Basic ") == 0) {
|
||||||
|
base64 = std::string(header, 6, header.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
base64 = Utils::Base64::decode(base64);
|
base64 = Utils::Base64::decode(base64);
|
||||||
@ -61,8 +63,18 @@ void RemoteUser::evaluate(Transaction *transaction,
|
|||||||
}
|
}
|
||||||
transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos));
|
transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos));
|
||||||
|
|
||||||
l->push_back(new collection::Variable(&m_retName,
|
var = new collection::Variable(l->at(0)->m_key,
|
||||||
&transaction->m_variableRemoteUser));
|
&transaction->m_variableRemoteUser);
|
||||||
|
|
||||||
|
for (auto &i : l->at(0)->m_orign) {
|
||||||
|
std::unique_ptr<VariableOrigin> 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,4 +21,12 @@
|
|||||||
./test/fuzzer
|
./test/fuzzer
|
||||||
./test/libfuzzer
|
./test/libfuzzer
|
||||||
./src/parser/seclang-parser.tab.cc
|
./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
|
Total errors found
|
||||||
|
@ -31,6 +31,7 @@ class CustomDebugLog : public modsecurity::debug_log::DebugLog {
|
|||||||
void write(int level, const std::string& message) override;
|
void write(int level, const std::string& message) override;
|
||||||
bool contains(const std::string& pattern);
|
bool contains(const std::string& pattern);
|
||||||
std::string log_messages();
|
std::string log_messages();
|
||||||
|
std::string error_log_messages();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::stringstream m_log;
|
std::stringstream m_log;
|
||||||
|
@ -475,7 +475,7 @@ int main(int argc, char **argv) {
|
|||||||
if (r->passed == true && r->skipped == false) {
|
if (r->passed == true && r->skipped == false) {
|
||||||
passed++;
|
passed++;
|
||||||
} else if (r->skipped == false) {
|
} else if (r->skipped == false) {
|
||||||
if (test.m_automake_output && 1 == 0) {
|
if (test.m_automake_output) {
|
||||||
// m_automake_output
|
// m_automake_output
|
||||||
} else {
|
} else {
|
||||||
std::cout << KRED << "Test failed." << RESET << KWHT \
|
std::cout << KRED << "Test failed." << RESET << KWHT \
|
||||||
|
@ -66,15 +66,15 @@ inline std::vector<std::string> RegressionTest::yajl_array_to_vec_str(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline std::unordered_map<std::string, std::string>
|
inline std::vector<std::pair<std::string, std::string>>
|
||||||
RegressionTest::yajl_array_to_map(const yajl_val &node) {
|
RegressionTest::yajl_array_to_map(const yajl_val &node) {
|
||||||
std::unordered_map<std::string, std::string> vec;
|
std::vector<std::pair<std::string, std::string>> vec;
|
||||||
for (int z = 0; z < node->u.object.len; z++) {
|
for (int z = 0; z < node->u.object.len; z++) {
|
||||||
const char *key = node->u.object.keys[z];
|
const char *key = node->u.object.keys[z];
|
||||||
yajl_val val3 = node->u.object.values[z];
|
yajl_val val3 = node->u.object.values[z];
|
||||||
const char *value = YAJL_GET_STRING(val3);
|
const char *value = YAJL_GET_STRING(val3);
|
||||||
std::pair<std::string, std::string> a(key, value);
|
std::pair<std::string, std::string> a(key, value);
|
||||||
vec.insert(a);
|
vec.push_back(a);
|
||||||
}
|
}
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,10 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#ifndef TEST_REGRESSION_REGRESSION_TEST_H_
|
#ifndef TEST_REGRESSION_REGRESSION_TEST_H_
|
||||||
#define TEST_REGRESSION_REGRESSION_TEST_H_
|
#define TEST_REGRESSION_REGRESSION_TEST_H_
|
||||||
@ -44,8 +46,8 @@ class RegressionTest {
|
|||||||
int version_max;
|
int version_max;
|
||||||
int github_issue;
|
int github_issue;
|
||||||
|
|
||||||
std::unordered_map<std::string, std::string> request_headers;
|
std::vector<std::pair<std::string, std::string>> request_headers;
|
||||||
std::unordered_map<std::string, std::string> response_headers;
|
std::vector<std::pair<std::string, std::string>> response_headers;
|
||||||
std::string request_body;
|
std::string request_body;
|
||||||
std::string response_body;
|
std::string response_body;
|
||||||
std::string response_protocol;
|
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::string yajl_array_to_str(const yajl_val &node);
|
||||||
static inline std::vector<std::string> yajl_array_to_vec_str(
|
static inline std::vector<std::string> yajl_array_to_vec_str(
|
||||||
const yajl_val &node);
|
const yajl_val &node);
|
||||||
static inline std::unordered_map<std::string,
|
static inline std::vector<std::pair<std::string, std::string>>
|
||||||
std::string> yajl_array_to_map(const yajl_val &node);
|
yajl_array_to_map(const yajl_val &node);
|
||||||
|
|
||||||
int http_code;
|
int http_code;
|
||||||
std::string redirect_url;
|
std::string redirect_url;
|
||||||
|
1955
test/test-cases/regression/offset-variable.json
Normal file
1955
test/test-cases/regression/offset-variable.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -51,7 +51,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"expected":{
|
"expected":{
|
||||||
"debug_log":"T \\(0\\) t:trim: \"filedata"
|
"debug_log":"T \\(0\\) t:trim: \"small_text"
|
||||||
},
|
},
|
||||||
"rules":[
|
"rules":[
|
||||||
"SecRuleEngine On",
|
"SecRuleEngine On",
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"expected":{
|
"expected":{
|
||||||
"debug_log":"Content-Type: multipart/form-data; boundary=------------"
|
"debug_log":"Multipart: Boundary: --------------------------756b6d74fa1a8ee2"
|
||||||
},
|
},
|
||||||
"rules":[
|
"rules":[
|
||||||
"SecRuleEngine On",
|
"SecRuleEngine On",
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"expected":{
|
"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":[
|
"rules":[
|
||||||
"SecRuleEngine On",
|
"SecRuleEngine On",
|
||||||
|
@ -240,7 +240,7 @@ int main(int argc, char **argv) {
|
|||||||
} else {
|
} else {
|
||||||
for (auto &i : r) {
|
for (auto &i : r) {
|
||||||
if (i->skipped == true) {
|
if (i->skipped == true) {
|
||||||
skp++;
|
skp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << KRED << r.size()-skp << " tests failed.";
|
std::cout << KRED << r.size()-skp << " tests failed.";
|
||||||
@ -275,7 +275,7 @@ int main(int argc, char **argv) {
|
|||||||
int skp = 0;
|
int skp = 0;
|
||||||
for (auto &i : results) {
|
for (auto &i : results) {
|
||||||
if (i->skipped == true) {
|
if (i->skipped == true) {
|
||||||
skp++;
|
skp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << KRED << results.size()-skp << " failed.";
|
std::cout << KRED << results.size()-skp << " failed.";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user