mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-17 02:56:08 +03:00
Adds support to the cssDecode transformation
This commit is contained in:
parent
1924b4ebca
commit
ce298165dd
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
#include "actions/transformations/css_decode.h"
|
#include "actions/transformations/css_decode.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -24,26 +26,24 @@
|
|||||||
|
|
||||||
#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 {
|
||||||
|
|
||||||
CssDecode::CssDecode(std::string action)
|
|
||||||
: Transformation(action) {
|
|
||||||
this->action_kind = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CssDecode::evaluate(std::string value,
|
std::string CssDecode::evaluate(std::string value,
|
||||||
Assay *assay) {
|
Assay *assay) {
|
||||||
/**
|
char *tmp = strdup(value.c_str());
|
||||||
* @todo Implement the transformation CssDecode
|
int res = css_decode_inplace((unsigned char *)tmp, value.size());
|
||||||
*/
|
std::string ret(tmp, 0, value.size());
|
||||||
assay->debug(4, "Transformation CssDecode is not implemented yet.");
|
free(tmp);
|
||||||
return value;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace transformations
|
} // namespace transformations
|
||||||
} // namespace actions
|
} // namespace actions
|
||||||
} // namespace ModSecurity
|
} // namespace ModSecurity
|
||||||
|
@ -28,13 +28,16 @@ class Assay;
|
|||||||
namespace actions {
|
namespace actions {
|
||||||
namespace transformations {
|
namespace transformations {
|
||||||
|
|
||||||
|
|
||||||
class CssDecode : public Transformation {
|
class CssDecode : public Transformation {
|
||||||
public:
|
public:
|
||||||
explicit CssDecode(std::string action);
|
explicit CssDecode(std::string action)
|
||||||
|
: Transformation(action) { }
|
||||||
std::string evaluate(std::string exp,
|
std::string evaluate(std::string exp,
|
||||||
Assay *assay) override;
|
Assay *assay) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace transformations
|
} // namespace transformations
|
||||||
} // namespace actions
|
} // namespace actions
|
||||||
} // namespace ModSecurity
|
} // namespace ModSecurity
|
||||||
|
@ -77,7 +77,7 @@ Transformation* Transformation::instantiate(std::string a) {
|
|||||||
IF_MATCH(base64_decode) { return new Base64Decode(a); }
|
IF_MATCH(base64_decode) { return new Base64Decode(a); }
|
||||||
IF_MATCH(cmd_line) { return new CmdLine(a); }
|
IF_MATCH(cmd_line) { return new CmdLine(a); }
|
||||||
IF_MATCH(compress_whitespace) { return new CompressWhitespace(a); }
|
IF_MATCH(compress_whitespace) { return new CompressWhitespace(a); }
|
||||||
IF_MATCH(css_decode) { return new CssDecode(a); }
|
IF_MATCH(cssDecode) { return new CssDecode(a); }
|
||||||
IF_MATCH(escape_seq_decode) { return new EscapeSeqDecode(a); }
|
IF_MATCH(escape_seq_decode) { return new EscapeSeqDecode(a); }
|
||||||
IF_MATCH(hex_decode) { return new HexDecode(a); }
|
IF_MATCH(hex_decode) { return new HexDecode(a); }
|
||||||
IF_MATCH(hex_encode) { return new HexEncode(a); }
|
IF_MATCH(hex_encode) { return new HexEncode(a); }
|
||||||
|
152
src/utils.cc
152
src/utils.cc
@ -328,6 +328,158 @@ int js_decode_nonstrict_inplace(unsigned char *input, int64_t input_len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a string that contains CSS-escaped characters.
|
||||||
|
*
|
||||||
|
* References:
|
||||||
|
* http://www.w3.org/TR/REC-CSS2/syndata.html#q4
|
||||||
|
* http://www.unicode.org/roadmaps/
|
||||||
|
*/
|
||||||
|
int css_decode_inplace(unsigned char *input, int64_t input_len) {
|
||||||
|
unsigned char *d = (unsigned char *)input;
|
||||||
|
int64_t i, j, count;
|
||||||
|
|
||||||
|
if (input == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = count = 0;
|
||||||
|
while (i < input_len) {
|
||||||
|
/* Is the character a backslash? */
|
||||||
|
if (input[i] == '\\') {
|
||||||
|
/* Is there at least one more byte? */
|
||||||
|
if (i + 1 < input_len) {
|
||||||
|
i++; /* We are not going to need the backslash. */
|
||||||
|
|
||||||
|
/* Check for 1-6 hex characters following the backslash */
|
||||||
|
j = 0;
|
||||||
|
while ((j < 6)
|
||||||
|
&& (i + j < input_len)
|
||||||
|
&& (VALID_HEX(input[i + j]))) {
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j > 0) {
|
||||||
|
/* We have at least one valid hexadecimal character. */
|
||||||
|
int fullcheck = 0;
|
||||||
|
|
||||||
|
/* For now just use the last two bytes. */
|
||||||
|
switch (j) {
|
||||||
|
/* Number of hex characters */
|
||||||
|
case 1:
|
||||||
|
*d++ = xsingle2c(&input[i]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
/* Use the last two from the end. */
|
||||||
|
*d++ = x2c(&input[i + j - 2]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
/* Use the last two from the end, but request
|
||||||
|
* a full width check.
|
||||||
|
*/
|
||||||
|
*d = x2c(&input[i + j - 2]);
|
||||||
|
fullcheck = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
/* Use the last two from the end, but request
|
||||||
|
* a full width check if the number is greater
|
||||||
|
* or equal to 0xFFFF.
|
||||||
|
*/
|
||||||
|
*d = x2c(&input[i + j - 2]);
|
||||||
|
/* Do full check if first byte is 0 */
|
||||||
|
if (input[i] == '0') {
|
||||||
|
fullcheck = 1;
|
||||||
|
} else {
|
||||||
|
d++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
/* Use the last two from the end, but request
|
||||||
|
* a full width check if the number is greater
|
||||||
|
* or equal to 0xFFFF.
|
||||||
|
*/
|
||||||
|
*d = x2c(&input[i + j - 2]);
|
||||||
|
|
||||||
|
/* Do full check if first/second bytes are 0 */
|
||||||
|
if ((input[i] == '0')
|
||||||
|
&& (input[i + 1] == '0')) {
|
||||||
|
fullcheck = 1;
|
||||||
|
} else {
|
||||||
|
d++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Full width ASCII (0xff01 - 0xff5e) needs 0x20 added */
|
||||||
|
if (fullcheck) {
|
||||||
|
if ((*d > 0x00) && (*d < 0x5f)
|
||||||
|
&& ((input[i + j - 3] == 'f') ||
|
||||||
|
(input[i + j - 3] == 'F'))
|
||||||
|
&& ((input[i + j - 4] == 'f') ||
|
||||||
|
(input[i + j - 4] == 'F'))) {
|
||||||
|
(*d) += 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
d++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We must ignore a single whitespace after a hex escape */
|
||||||
|
if ((i + j < input_len) && isspace(input[i + j])) {
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move over. */
|
||||||
|
count++;
|
||||||
|
i += j;
|
||||||
|
} else if (input[i] == '\n') {
|
||||||
|
/* No hexadecimal digits after backslash */
|
||||||
|
/* A newline character following backslash is ignored. */
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
/* The character after backslash is not a hexadecimal digit,
|
||||||
|
* nor a newline. */
|
||||||
|
/* Use one character after backslash as is. */
|
||||||
|
*d++ = input[i++];
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* No characters after backslash. */
|
||||||
|
/* Do not include backslash in output
|
||||||
|
*(continuation to nothing) */
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Character is not a backslash. */
|
||||||
|
/* Copy one normal character to output. */
|
||||||
|
*d++ = input[i++];
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminate output string. */
|
||||||
|
*d = '\0';
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a single hexadecimal digit into a decimal value.
|
||||||
|
*/
|
||||||
|
static unsigned char xsingle2c(unsigned char *what) {
|
||||||
|
register unsigned char digit;
|
||||||
|
|
||||||
|
digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
|
||||||
|
|
||||||
|
return digit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static unsigned char x2c(unsigned char *what) {
|
static unsigned char x2c(unsigned char *what) {
|
||||||
register unsigned char digit;
|
register unsigned char digit;
|
||||||
|
|
||||||
|
@ -35,6 +35,8 @@ namespace ModSecurity {
|
|||||||
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);
|
static unsigned char x2c(unsigned char *what);
|
||||||
|
int css_decode_inplace(unsigned char *input, int64_t input_len);
|
||||||
|
static unsigned char xsingle2c(unsigned char *what);
|
||||||
} // namespace ModSecurity
|
} // namespace ModSecurity
|
||||||
|
|
||||||
#define SRC_UTILS_H_
|
#define SRC_UTILS_H_
|
||||||
|
Loading…
x
Reference in New Issue
Block a user