mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-16 07:56:12 +03:00
Adds support to URL decode transformation
This commit is contained in:
parent
0227fe9d6c
commit
e3e8bac138
@ -106,7 +106,7 @@ Transformation* Transformation::instantiate(std::string a) {
|
|||||||
IF_MATCH(trimLeft) { return new TrimLeft(a); }
|
IF_MATCH(trimLeft) { return new TrimLeft(a); }
|
||||||
IF_MATCH(trimRight) { return new TrimRight(a); }
|
IF_MATCH(trimRight) { return new TrimRight(a); }
|
||||||
IF_MATCH(trim) { return new Trim(a); }
|
IF_MATCH(trim) { return new Trim(a); }
|
||||||
IF_MATCH(url_decode) { return new UrlDecode(a); }
|
IF_MATCH(urlDecode) { return new UrlDecode(a); }
|
||||||
IF_MATCH(urlDecodeUni) { return new UrlDecodeUni(a); }
|
IF_MATCH(urlDecodeUni) { return new UrlDecodeUni(a); }
|
||||||
IF_MATCH(url_encode) { return new UrlEncode(a); }
|
IF_MATCH(url_encode) { return new UrlEncode(a); }
|
||||||
IF_MATCH(utf8_to_unicode) { return new Utf8Unicode(a); }
|
IF_MATCH(utf8_to_unicode) { return new Utf8Unicode(a); }
|
||||||
|
@ -24,12 +24,71 @@
|
|||||||
|
|
||||||
#include "modsecurity/assay.h"
|
#include "modsecurity/assay.h"
|
||||||
#include "actions/transformations/transformation.h"
|
#include "actions/transformations/transformation.h"
|
||||||
|
#include "src/utils.h"
|
||||||
|
|
||||||
namespace ModSecurity {
|
namespace ModSecurity {
|
||||||
namespace actions {
|
namespace actions {
|
||||||
namespace transformations {
|
namespace transformations {
|
||||||
|
|
||||||
|
|
||||||
|
int UrlDecode::urldecode_nonstrict_inplace(unsigned char *input,
|
||||||
|
long int input_len, int *invalid_count, int *changed) {
|
||||||
|
unsigned char *d = (unsigned char *)input;
|
||||||
|
long int 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)) {
|
||||||
|
unsigned long 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)
|
UrlDecode::UrlDecode(std::string action)
|
||||||
: Transformation(action) {
|
: Transformation(action) {
|
||||||
this->action_kind = 1;
|
this->action_kind = 1;
|
||||||
@ -37,17 +96,25 @@ UrlDecode::UrlDecode(std::string action)
|
|||||||
|
|
||||||
std::string UrlDecode::evaluate(std::string value,
|
std::string UrlDecode::evaluate(std::string value,
|
||||||
Assay *assay) {
|
Assay *assay) {
|
||||||
/**
|
unsigned char *val = NULL;
|
||||||
* @todo Implement the transformation UrlDecode
|
int invalid_count;
|
||||||
*/
|
int changed;
|
||||||
if (assay) {
|
|
||||||
#ifndef NO_LOGS
|
val = (unsigned char *) malloc(sizeof(char) * value.size() + 1);
|
||||||
assay->debug(4, "Transformation UrlDecode is not implemented yet.");
|
memcpy(val, value.c_str(), value.size() + 1);
|
||||||
#endif
|
val[value.size()] = '\0';
|
||||||
}
|
|
||||||
return value;
|
int size = urldecode_nonstrict_inplace(val, value.size(), &invalid_count, &changed);
|
||||||
|
std::string out;
|
||||||
|
|
||||||
|
out.append((const char *)val, size);
|
||||||
|
|
||||||
|
free(val);
|
||||||
|
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace transformations
|
} // namespace transformations
|
||||||
} // namespace actions
|
} // namespace actions
|
||||||
} // namespace ModSecurity
|
} // namespace ModSecurity
|
||||||
|
@ -33,6 +33,9 @@ class UrlDecode : public Transformation {
|
|||||||
explicit UrlDecode(std::string action);
|
explicit UrlDecode(std::string action);
|
||||||
std::string evaluate(std::string exp,
|
std::string evaluate(std::string exp,
|
||||||
Assay *assay) override;
|
Assay *assay) override;
|
||||||
|
|
||||||
|
int urldecode_nonstrict_inplace(unsigned char *input, long int input_len,
|
||||||
|
int *invalid_count, int *changed);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace transformations
|
} // namespace transformations
|
||||||
|
@ -43,11 +43,6 @@
|
|||||||
|
|
||||||
#include "modsecurity/modsecurity.h"
|
#include "modsecurity/modsecurity.h"
|
||||||
|
|
||||||
#define VALID_HEX(X) (((X >= '0') && (X <= '9')) || \
|
|
||||||
((X >= 'a') && (X <= 'f')) || ((X >= 'A') && (X <= 'F')))
|
|
||||||
#define ISODIGIT(X) ((X >= '0') && (X <= '7'))
|
|
||||||
#define NBSP 160
|
|
||||||
|
|
||||||
namespace ModSecurity {
|
namespace ModSecurity {
|
||||||
|
|
||||||
std::string phase_name(int x) {
|
std::string phase_name(int x) {
|
||||||
@ -827,7 +822,7 @@ length:
|
|||||||
/**
|
/**
|
||||||
* Converts a single hexadecimal digit into a decimal value.
|
* Converts a single hexadecimal digit into a decimal value.
|
||||||
*/
|
*/
|
||||||
static unsigned char xsingle2c(unsigned char *what) {
|
unsigned char xsingle2c(unsigned char *what) {
|
||||||
register unsigned char digit;
|
register unsigned char digit;
|
||||||
|
|
||||||
digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
|
digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
|
||||||
@ -836,7 +831,7 @@ static unsigned char xsingle2c(unsigned char *what) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static unsigned char x2c(unsigned char *what) {
|
unsigned char x2c(unsigned char *what) {
|
||||||
register unsigned char digit;
|
register unsigned char digit;
|
||||||
|
|
||||||
digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
|
digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
|
||||||
|
11
src/utils.h
11
src/utils.h
@ -22,6 +22,13 @@
|
|||||||
|
|
||||||
#ifndef SRC_UTILS_H_
|
#ifndef SRC_UTILS_H_
|
||||||
|
|
||||||
|
|
||||||
|
#define VALID_HEX(X) (((X >= '0') && (X <= '9')) || \
|
||||||
|
((X >= 'a') && (X <= 'f')) || ((X >= 'A') && (X <= 'F')))
|
||||||
|
#define ISODIGIT(X) ((X >= '0') && (X <= '7'))
|
||||||
|
#define NBSP 160
|
||||||
|
|
||||||
|
|
||||||
namespace ModSecurity {
|
namespace ModSecurity {
|
||||||
std::vector<std::string> split(std::string str, char delimiter);
|
std::vector<std::string> split(std::string str, char delimiter);
|
||||||
double random_number(const double from, const double to);
|
double random_number(const double from, const double to);
|
||||||
@ -35,9 +42,9 @@ namespace ModSecurity {
|
|||||||
std::string toupper(std::string str);
|
std::string toupper(std::string str);
|
||||||
double cpu_seconds(void);
|
double cpu_seconds(void);
|
||||||
int js_decode_nonstrict_inplace(unsigned char *input, int64_t input_len);
|
int js_decode_nonstrict_inplace(unsigned char *input, int64_t input_len);
|
||||||
static unsigned char x2c(unsigned char *what);
|
unsigned char x2c(unsigned char *what);
|
||||||
int css_decode_inplace(unsigned char *input, int64_t input_len);
|
int css_decode_inplace(unsigned char *input, int64_t input_len);
|
||||||
static unsigned char xsingle2c(unsigned char *what);
|
unsigned char xsingle2c(unsigned char *what);
|
||||||
int html_entities_decode_inplace(unsigned char *input, int input_len);
|
int html_entities_decode_inplace(unsigned char *input, int input_len);
|
||||||
int normalize_path_inplace(unsigned char *input, int input_len,
|
int normalize_path_inplace(unsigned char *input, int input_len,
|
||||||
int win, int *changed);
|
int win, int *changed);
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 1f6f5235485e4a68f9cd57d2ac1ad4a0d4a7a3c4
|
Subproject commit 76c4bd6460a870b481eb4d36fcead7818b20d7d9
|
@ -93,6 +93,11 @@ UnitTest *UnitTest::from_yajl_node(yajl_val &node) {
|
|||||||
u->param = YAJL_GET_STRING(val);
|
u->param = YAJL_GET_STRING(val);
|
||||||
} else if (strcmp(key, "input") == 0) {
|
} else if (strcmp(key, "input") == 0) {
|
||||||
u->input = YAJL_GET_STRING(val);
|
u->input = YAJL_GET_STRING(val);
|
||||||
|
/*
|
||||||
|
* Converting \\u0000 to \0 due to the following gcc bug:
|
||||||
|
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53690
|
||||||
|
*
|
||||||
|
*/
|
||||||
replaceAll(&(u->input), "\\0", '\0');
|
replaceAll(&(u->input), "\\0", '\0');
|
||||||
replaceAll(&(u->input), "\\xe4", '\xe4');
|
replaceAll(&(u->input), "\\xe4", '\xe4');
|
||||||
replaceAll(&(u->input), "\\x03", '\x03');
|
replaceAll(&(u->input), "\\x03", '\x03');
|
||||||
@ -100,7 +105,7 @@ UnitTest *UnitTest::from_yajl_node(yajl_val &node) {
|
|||||||
replaceAll(&(u->input), "\\xc9", '\xc9');
|
replaceAll(&(u->input), "\\xc9", '\xc9');
|
||||||
replaceAll(&(u->input), "\\x3b", '\x3b');
|
replaceAll(&(u->input), "\\x3b", '\x3b');
|
||||||
replaceAll(&(u->input), "\\xFF", '\xff');
|
replaceAll(&(u->input), "\\xFF", '\xff');
|
||||||
replaceAll(&(u->input), "\\u0000", '\u0000');
|
replaceAll(&(u->input), "\\u0000", '\0');
|
||||||
} else if (strcmp(key, "name") == 0) {
|
} else if (strcmp(key, "name") == 0) {
|
||||||
u->name = YAJL_GET_STRING(val);
|
u->name = YAJL_GET_STRING(val);
|
||||||
} else if (strcmp(key, "type") == 0) {
|
} else if (strcmp(key, "type") == 0) {
|
||||||
@ -108,9 +113,20 @@ UnitTest *UnitTest::from_yajl_node(yajl_val &node) {
|
|||||||
} else if (strcmp(key, "ret") == 0) {
|
} else if (strcmp(key, "ret") == 0) {
|
||||||
u->ret = YAJL_GET_INTEGER(val);
|
u->ret = YAJL_GET_INTEGER(val);
|
||||||
} else if (strcmp(key, "output") == 0) {
|
} else if (strcmp(key, "output") == 0) {
|
||||||
u->output = YAJL_GET_STRING(val);
|
u->output = std::string(YAJL_GET_STRING(val));
|
||||||
replaceAll(&(u->output), "\\u0000", '\u0000');
|
/*
|
||||||
replaceAll(&(u->output), "\\0", '\u0000');
|
* Converting \\u0000 to \0 due to the following gcc bug:
|
||||||
|
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53690
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
replaceAll(&(u->output), "\\u0000", '\0');
|
||||||
|
replaceAll(&(u->output), "\\xe4", '\xe4');
|
||||||
|
replaceAll(&(u->output), "\\x03", '\x03');
|
||||||
|
replaceAll(&(u->output), "\\xbf", '\xbf');
|
||||||
|
replaceAll(&(u->output), "\\xc9", '\xc9');
|
||||||
|
replaceAll(&(u->output), "\\x3b", '\x3b');
|
||||||
|
replaceAll(&(u->output), "\\xFF", '\xff');
|
||||||
|
replaceAll(&(u->output), "\\0", '\0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user