mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 05:45:59 +03:00
Adds support to urlDecodeUni transformation
This commit is contained in:
parent
6dad6af4a9
commit
522f195aa0
@ -191,9 +191,10 @@ class Assay {
|
||||
clock_t start;
|
||||
int highest_severity;
|
||||
|
||||
Rules *m_rules;
|
||||
|
||||
private:
|
||||
std::ofstream myfile;
|
||||
Rules *m_rules;
|
||||
ModSecurity *m_ms;
|
||||
|
||||
const char *m_clientIpAddress;
|
||||
|
@ -13,6 +13,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
@ -47,10 +50,20 @@ class Driver;
|
||||
class Rules : public RulesProperties {
|
||||
public:
|
||||
Rules()
|
||||
: RulesProperties(NULL) { }
|
||||
: RulesProperties(NULL),
|
||||
unicode_codepage(0) {
|
||||
unicode_map_table = reinterpret_cast<int *>(
|
||||
malloc(sizeof(int)*65536));
|
||||
memset(unicode_map_table, -1, (sizeof(int)*65536));
|
||||
}
|
||||
|
||||
explicit Rules(DebugLog *customLog)
|
||||
: RulesProperties(customLog) { }
|
||||
: unicode_codepage(0),
|
||||
RulesProperties(customLog) {
|
||||
unicode_map_table = reinterpret_cast<int *>(
|
||||
malloc(sizeof(int)*65536));
|
||||
memset(unicode_map_table, -1, (sizeof(int)*65536));
|
||||
}
|
||||
|
||||
~Rules();
|
||||
|
||||
@ -76,6 +89,9 @@ class Rules : public RulesProperties {
|
||||
|
||||
DebugLog *debugLog;
|
||||
|
||||
int *unicode_map_table;
|
||||
int64_t unicode_codepage;
|
||||
|
||||
private:
|
||||
int m_referenceCount;
|
||||
};
|
||||
|
@ -105,7 +105,7 @@ Transformation* Transformation::instantiate(std::string a) {
|
||||
IF_MATCH(trim_left) { return new TrimLeft(a); }
|
||||
IF_MATCH(trim_right) { return new TrimRight(a); }
|
||||
IF_MATCH(url_decode) { return new UrlDecode(a); }
|
||||
IF_MATCH(url_decode_uni) { return new UrlDecodeUni(a); }
|
||||
IF_MATCH(urlDecodeUni) { return new UrlDecodeUni(a); }
|
||||
IF_MATCH(url_encode) { return new UrlEncode(a); }
|
||||
IF_MATCH(utf8_to_unicode) { return new Utf8Unicode(a); }
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
|
||||
#include "actions/transformations/url_decode_uni.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
@ -24,26 +26,28 @@
|
||||
|
||||
#include "modsecurity/assay.h"
|
||||
#include "actions/transformations/transformation.h"
|
||||
#include "src/utils.h"
|
||||
|
||||
|
||||
namespace ModSecurity {
|
||||
namespace actions {
|
||||
namespace transformations {
|
||||
|
||||
UrlDecodeUni::UrlDecodeUni(std::string action)
|
||||
: Transformation(action) {
|
||||
this->action_kind = 1;
|
||||
}
|
||||
|
||||
std::string UrlDecodeUni::evaluate(std::string value,
|
||||
Assay *assay) {
|
||||
/**
|
||||
* @todo Implement the transformation UrlDecodeUni
|
||||
*/
|
||||
assay->debug(4, "Transformation UrlDecodeUni is not implemented yet.");
|
||||
return value;
|
||||
int changed = 0;
|
||||
char *tmp = strdup(value.c_str());
|
||||
int res = urldecode_uni_nonstrict_inplace_ex(assay, (unsigned char *)tmp,
|
||||
value.size(), &changed);
|
||||
std::string ret("");
|
||||
ret.assign(tmp);
|
||||
free(tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
} // namespace transformations
|
||||
} // namespace actions
|
||||
} // namespace ModSecurity
|
||||
|
@ -30,7 +30,9 @@ namespace transformations {
|
||||
|
||||
class UrlDecodeUni : public Transformation {
|
||||
public:
|
||||
explicit UrlDecodeUni(std::string action);
|
||||
explicit UrlDecodeUni(std::string action)
|
||||
: Transformation(action) { }
|
||||
|
||||
std::string evaluate(std::string exp,
|
||||
Assay *assay) override;
|
||||
};
|
||||
|
132
src/utils.cc
132
src/utils.cc
@ -824,5 +824,137 @@ std::string string_to_hex(const std::string& input) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* IMP1 Assumes NUL-terminated
|
||||
*/
|
||||
int urldecode_uni_nonstrict_inplace_ex(Assay *assay, unsigned char *input,
|
||||
int64_t input_len, int *changed) {
|
||||
unsigned char *d = input;
|
||||
int64_t i, count, fact, j, xv;
|
||||
int Code, hmap = -1;
|
||||
|
||||
*changed = 0;
|
||||
|
||||
if (input == NULL) return -1;
|
||||
|
||||
i = count = 0;
|
||||
while (i < input_len) {
|
||||
if (input[i] == '%') {
|
||||
if ((i + 1 < input_len) &&
|
||||
((input[i + 1] == 'u') || (input[i + 1] == 'U'))) {
|
||||
/* Character is a percent sign. */
|
||||
/* IIS-specific %u encoding. */
|
||||
if (i + 5 < input_len) {
|
||||
/* We have at least 4 data bytes. */
|
||||
if ((VALID_HEX(input[i + 2])) &&
|
||||
(VALID_HEX(input[i + 3])) &&
|
||||
(VALID_HEX(input[i + 4])) &&
|
||||
(VALID_HEX(input[i + 5]))) {
|
||||
Code = 0;
|
||||
fact = 1;
|
||||
|
||||
if (assay
|
||||
&& assay->m_rules->unicode_map_table != NULL
|
||||
&& assay->m_rules->unicode_codepage > 0) {
|
||||
for (j = 5; j >= 2; j--) {
|
||||
if (isxdigit((input[i+j]))) {
|
||||
if (input[i+j] >= 97) {
|
||||
xv = (input[i+j] - 97) + 10;
|
||||
} else if (input[i+j] >= 65) {
|
||||
xv = (input[i+j] - 65) + 10;
|
||||
} else {
|
||||
xv = (input[i+j]) - 48;
|
||||
}
|
||||
Code += (xv * fact);
|
||||
fact *= 16;
|
||||
}
|
||||
}
|
||||
|
||||
if (Code >= 0 && Code <= 65535) {
|
||||
hmap = assay->m_rules->unicode_map_table[Code];
|
||||
}
|
||||
}
|
||||
|
||||
if (hmap != -1) {
|
||||
*d = hmap;
|
||||
} else {
|
||||
/* We first make use of the lower byte here,
|
||||
* ignoring the higher byte. */
|
||||
*d = x2c(&input[i + 4]);
|
||||
|
||||
/* Full width ASCII (ff01 - ff5e)
|
||||
* needs 0x20 added */
|
||||
if ((*d > 0x00) && (*d < 0x5f)
|
||||
&& ((input[i + 2] == 'f')
|
||||
|| (input[i + 2] == 'F'))
|
||||
&& ((input[i + 3] == 'f')
|
||||
|| (input[i + 3] == 'F'))) {
|
||||
(*d) += 0x20;
|
||||
}
|
||||
}
|
||||
d++;
|
||||
count++;
|
||||
i += 6;
|
||||
*changed = 1;
|
||||
} else {
|
||||
/* Invalid data, skip %u. */
|
||||
*d++ = input[i++];
|
||||
*d++ = input[i++];
|
||||
count += 2;
|
||||
}
|
||||
} else {
|
||||
/* Not enough bytes (4 data bytes), skip %u. */
|
||||
*d++ = input[i++];
|
||||
*d++ = input[i++];
|
||||
count += 2;
|
||||
}
|
||||
} else {
|
||||
/* Standard URL encoding. */
|
||||
/* Are there enough bytes available? */
|
||||
if (i + 2 < input_len) {
|
||||
/* Yes. */
|
||||
|
||||
/* Decode a %xx combo only if it is valid.
|
||||
*/
|
||||
char c1 = input[i + 1];
|
||||
char c2 = input[i + 2];
|
||||
|
||||
if (VALID_HEX(c1) && VALID_HEX(c2)) {
|
||||
*d++ = x2c(&input[i + 1]);
|
||||
count++;
|
||||
i += 3;
|
||||
*changed = 1;
|
||||
} else {
|
||||
/* Not a valid encoding, skip this % */
|
||||
*d++ = input[i++];
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
/* Not enough bytes available, skip this % */
|
||||
*d++ = input[i++];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Character is not a percent sign. */
|
||||
if (input[i] == '+') {
|
||||
*d++ = ' ';
|
||||
*changed = 1;
|
||||
} else {
|
||||
*d++ = input[i];
|
||||
}
|
||||
|
||||
count++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
*d = '\0';
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ModSecurity
|
||||
|
||||
|
@ -41,6 +41,8 @@ namespace ModSecurity {
|
||||
int normalize_path_inplace(unsigned char *input, int input_len,
|
||||
int win, int *changed);
|
||||
std::string string_to_hex(const std::string& input);
|
||||
int urldecode_uni_nonstrict_inplace_ex(Assay *assay, unsigned char *input,
|
||||
int64_t input_len, int *changed);
|
||||
} // namespace ModSecurity
|
||||
|
||||
#define SRC_UTILS_H_
|
||||
|
Loading…
x
Reference in New Issue
Block a user