mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 13:56:01 +03:00
163 lines
4.5 KiB
C++
163 lines
4.5 KiB
C++
/*
|
|
* ModSecurity, http://www.modsecurity.org/
|
|
* Copyright (c) 2015 - 2020 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
|
*
|
|
* You may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* If any of the files related to licensing are missing or if you have any
|
|
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
|
* directly using the email address security@modsecurity.org.
|
|
*
|
|
*/
|
|
|
|
#include "src/actions/transformations/escape_seq_decode.h"
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <algorithm>
|
|
#include <functional>
|
|
#include <cctype>
|
|
#include <locale>
|
|
#include <cstring>
|
|
|
|
#include "modsecurity/transaction.h"
|
|
#include "src/actions/transformations/transformation.h"
|
|
#include "src/utils/string.h"
|
|
|
|
namespace modsecurity {
|
|
namespace actions {
|
|
namespace transformations {
|
|
|
|
EscapeSeqDecode::EscapeSeqDecode(const std::string &action)
|
|
: Transformation(action) {
|
|
this->action_kind = 1;
|
|
}
|
|
|
|
|
|
int EscapeSeqDecode::ansi_c_sequences_decode_inplace(unsigned char *input,
|
|
int input_len) {
|
|
unsigned char *d = input;
|
|
int i, count;
|
|
|
|
i = count = 0;
|
|
while (i < input_len) {
|
|
if ((input[i] == '\\') && (i + 1 < input_len)) {
|
|
int c = -1;
|
|
|
|
switch (input[i + 1]) {
|
|
case 'a' :
|
|
c = '\a';
|
|
break;
|
|
case 'b' :
|
|
c = '\b';
|
|
break;
|
|
case 'f' :
|
|
c = '\f';
|
|
break;
|
|
case 'n' :
|
|
c = '\n';
|
|
break;
|
|
case 'r' :
|
|
c = '\r';
|
|
break;
|
|
case 't' :
|
|
c = '\t';
|
|
break;
|
|
case 'v' :
|
|
c = '\v';
|
|
break;
|
|
case '\\' :
|
|
c = '\\';
|
|
break;
|
|
case '?' :
|
|
c = '?';
|
|
break;
|
|
case '\'' :
|
|
c = '\'';
|
|
break;
|
|
case '"' :
|
|
c = '"';
|
|
break;
|
|
}
|
|
|
|
if (c != -1) i += 2;
|
|
|
|
/* Hexadecimal or octal? */
|
|
if (c == -1) {
|
|
if ((input[i + 1] == 'x') || (input[i + 1] == 'X')) {
|
|
/* Hexadecimal. */
|
|
if ((i + 3 < input_len) && (isxdigit(input[i + 2]))
|
|
&& (isxdigit(input[i + 3]))) {
|
|
/* Two digits. */
|
|
c = utils::string::x2c(&input[i + 2]);
|
|
i += 4;
|
|
} else {
|
|
/* Invalid encoding, do nothing. */
|
|
}
|
|
} else {
|
|
if (ISODIGIT(input[i + 1])) { /* Octal. */
|
|
char buf[4];
|
|
int j = 0;
|
|
|
|
while ((i + 1 + j < input_len) && (j < 3)) {
|
|
buf[j] = input[i + 1 + j];
|
|
j++;
|
|
if (!ISODIGIT(input[i + 1 + j])) break;
|
|
}
|
|
buf[j] = '\0';
|
|
|
|
if (j > 0) {
|
|
c = strtol(buf, NULL, 8);
|
|
i += 1 + j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (c == -1) {
|
|
/* Didn't recognise encoding, copy raw bytes. */
|
|
*d++ = input[i + 1];
|
|
count++;
|
|
i += 2;
|
|
} else {
|
|
/* Converted the encoding. */
|
|
*d++ = c;
|
|
count++;
|
|
}
|
|
} else {
|
|
/* Input character not a backslash, copy it. */
|
|
*d++ = input[i++];
|
|
count++;
|
|
}
|
|
}
|
|
|
|
*d = '\0';
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
std::string EscapeSeqDecode::execute(const std::string &value,
|
|
Transaction *transaction) {
|
|
|
|
unsigned char *tmp = (unsigned char *) malloc(sizeof(char)
|
|
* value.size() + 1);
|
|
memcpy(tmp, value.c_str(), value.size() + 1);
|
|
tmp[value.size()] = '\0';
|
|
|
|
int size = ansi_c_sequences_decode_inplace(tmp, value.size());
|
|
|
|
std::string ret("");
|
|
ret.assign(reinterpret_cast<char *>(tmp), size);
|
|
free(tmp);
|
|
|
|
return ret;
|
|
}
|
|
|
|
} // namespace transformations
|
|
} // namespace actions
|
|
} // namespace modsecurity
|