Adds support to URLENCODED_ERROR variable

This commit is contained in:
Felipe Zimmerle
2016-06-17 20:41:07 -03:00
parent c5262d54f2
commit 6052d2628b
9 changed files with 406 additions and 69 deletions

View File

@@ -31,64 +31,6 @@ namespace actions {
namespace transformations {
int UrlDecode::urldecode_nonstrict_inplace(unsigned char *input,
uint64_t input_len, int *invalid_count, int *changed) {
unsigned char *d = (unsigned char *)input;
uint64_t i, count;
*changed = 0;
if (input == NULL) {
return -1;
}
i = count = 0;
while (i < input_len) {
if (input[i] == '%') {
/* Character is a percent sign. */
/* Are there enough bytes available? */
if (i + 2 < input_len) {
char c1 = input[i + 1];
char c2 = input[i + 2];
if (VALID_HEX(c1) && VALID_HEX(c2)) {
uint64_t uni = x2c(&input[i + 1]);
*d++ = (wchar_t)uni;
count++;
i += 3;
*changed = 1;
} else {
/* Not a valid encoding, skip this % */
*d++ = input[i++];
count++;
(*invalid_count)++;
}
} else {
/* Not enough bytes available, copy the raw bytes. */
*d++ = input[i++];
count++;
(*invalid_count)++;
}
} else {
/* Character is not a percent sign. */
if (input[i] == '+') {
*d++ = ' ';
*changed = 1;
} else {
*d++ = input[i];
}
count++;
i++;
}
}
*d = '\0';
return count;
}
UrlDecode::UrlDecode(std::string action)
: Transformation(action) {
this->action_kind = 1;

View File

@@ -53,9 +53,6 @@ class UrlDecode : public Transformation {
explicit UrlDecode(std::string action);
std::string evaluate(std::string exp,
Transaction *transaction) override;
int urldecode_nonstrict_inplace(unsigned char *input, uint64_t input_len,
int *invalid_count, int *changed);
};
} // namespace transformations

View File

@@ -149,7 +149,7 @@ RUN_TIME_VAR_TIME_WDAY (?i:TIME_WDAY)
RUN_TIME_VAR_TIME_YEAR (?i:TIME_YEAR)
RUN_TIME_VAR_XML (?i:XML)
VARIABLENOCOLON (?i:REQBODY_PROCESSOR_ERROR_MSG|REQBODY_PROCESSOR_ERROR|REQBODY_PROCESSOR|REQBODY_ERROR_MSG|REQBODY_ERROR|MULTIPART_FILE_LIMIT_EXCEEDED|MULTIPART_INVALID_QUOTING|MULTIPART_HEADER_FOLDING|MULTIPART_INVALID_HEADER_FOLDING|MULTIPART_STRICT_ERROR|MULTIPART_UNMATCHED_BOUNDARY|REMOTE_ADDR|REQUEST_LINE)
VARIABLENOCOLON (?i:URLENCODED_ERROR|REQBODY_PROCESSOR_ERROR_MSG|REQBODY_PROCESSOR_ERROR|REQBODY_PROCESSOR|REQBODY_ERROR_MSG|REQBODY_ERROR|MULTIPART_FILE_LIMIT_EXCEEDED|MULTIPART_INVALID_QUOTING|MULTIPART_HEADER_FOLDING|MULTIPART_INVALID_HEADER_FOLDING|MULTIPART_STRICT_ERROR|MULTIPART_UNMATCHED_BOUNDARY|REMOTE_ADDR|REQUEST_LINE)
CONFIG_VALUE_ON (?i:On)

View File

@@ -140,6 +140,7 @@ Transaction::Transaction(ModSecurity *ms, Rules *rules, void *logCbData)
this->m_responseContentType = m_collections.resolveFirst(
"RESPONSE_CONTENT_TYPE");
m_collections.storeOrUpdateFirst("URLENCODED_ERROR", "0");
#ifndef NO_LOGS
this->debug(4, "Initialising transaction");
@@ -239,6 +240,10 @@ bool Transaction::extractArguments(const std::string &orig,
for (std::string t : key_value_sets) {
char sep2 = '=';
int i = 0;
size_t key_s = 0;
size_t value_s = 0;
int invalid = 0;
int changed = 0;
std::string key;
std::string value;
@@ -254,9 +259,29 @@ bool Transaction::extractArguments(const std::string &orig,
i++;
}
key = uri_decode(key);
value = uri_decode(value);
addArgument(orig, key, value);
key_s = (key.length() + 1);
value_s = (value.length() + 1);
unsigned char *key_c = (unsigned char *) malloc(sizeof(char) * key_s);
unsigned char *value_c = (unsigned char *) malloc(sizeof(char) * value_s);
memset(key_c, '\0', sizeof(char) * key_s);
memset(value_c, '\0', sizeof(char) * value_s);
memcpy(key_c, key.c_str(), key_s);
memcpy(value_c, value.c_str(), value_s);
key_s = urldecode_nonstrict_inplace(key_c, key_s, &invalid, &changed);
value_s = urldecode_nonstrict_inplace(value_c, value_s, &invalid, &changed);
if (invalid) {
m_collections.storeOrUpdateFirst("URLENCODED_ERROR", "1");
}
addArgument(orig, std::string((char *)key_c, key_s-1),
std::string((char *)value_c, value_s-1));
free(key_c);
free(value_c);
}
}

View File

@@ -73,6 +73,67 @@ std::string phase_name(int x) {
}
int urldecode_nonstrict_inplace(unsigned char *input,
uint64_t input_len, int *invalid_count, int *changed) {
unsigned char *d = (unsigned char *)input;
uint64_t i, count;
*changed = 0;
if (input == NULL) {
return -1;
}
i = count = 0;
while (i < input_len) {
if (input[i] == '%') {
/* Character is a percent sign. */
/* Are there enough bytes available? */
if (i + 2 < input_len) {
char c1 = input[i + 1];
char c2 = input[i + 2];
if (VALID_HEX(c1) && VALID_HEX(c2)) {
uint64_t uni = x2c(&input[i + 1]);
*d++ = (wchar_t)uni;
count++;
i += 3;
*changed = 1;
} else {
/* Not a valid encoding, skip this % */
*d++ = input[i++];
count++;
(*invalid_count)++;
}
} else {
/* Not enough bytes available, copy the raw bytes. */
*d++ = input[i++];
count++;
(*invalid_count)++;
}
} else {
/* Character is not a percent sign. */
if (input[i] == '+') {
*d++ = ' ';
*changed = 1;
} else {
*d++ = input[i];
}
count++;
i++;
}
}
#if 0
*d = '\0';
#endif
return count;
}
std::vector<std::string> split(std::string str, char delimiter) {
std::vector<std::string> internal;
std::stringstream ss(str); // Turn the string into a stream.

View File

@@ -31,6 +31,8 @@
namespace modsecurity {
std::vector<std::string> split(std::string str, char delimiter);
int urldecode_nonstrict_inplace(unsigned char *input,
uint64_t input_len, int *invalid_count, int *changed);
double random_number(const double from, const double to);
double generate_transaction_unique_id();
std::string ascTime(time_t *t);