From 1fe0e34201248e9f9bfb12ceefe5de1db01581d4 Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Wed, 25 May 2016 20:16:29 -0300 Subject: [PATCH] Adds support to sqlHexDecode transformation Issue #973 --- src/actions/transformations/sql_hex_decode.cc | 78 +++++++++++++++---- src/actions/transformations/sql_hex_decode.h | 15 +++- src/actions/transformations/transformation.cc | 2 +- test/test-cases/secrules-language-tests | 2 +- 4 files changed, 79 insertions(+), 18 deletions(-) diff --git a/src/actions/transformations/sql_hex_decode.cc b/src/actions/transformations/sql_hex_decode.cc index ffdf1943..b5579ee2 100644 --- a/src/actions/transformations/sql_hex_decode.cc +++ b/src/actions/transformations/sql_hex_decode.cc @@ -24,31 +24,83 @@ #include "modsecurity/transaction.h" #include "actions/transformations/transformation.h" +#include "src/utils.h" namespace modsecurity { namespace actions { namespace transformations { -SqlHexDecode::SqlHexDecode(std::string action) - : Transformation(action) { - this->action_kind = 1; -} +#ifndef VALID_HEX +#define VALID_HEX(X) (((X >= '0') && (X <= '9')) \ + || ((X >= 'a') && (X <= 'f')) \ + || ((X >= 'A') && (X <= 'F'))) +#endif +#ifndef ISODIGIT +#define ISODIGIT(X) ((X >= '0') && (X <= '7')) +#endif std::string SqlHexDecode::evaluate(std::string value, Transaction *transaction) { - /** - * @todo Implement the transformation SqlHexDecode - */ - if (transaction) { -#ifndef NO_LOGS - transaction->debug(4, "Transformation SqlHexDecode " \ - "is not implemented yet."); -#endif + std::string ret; + unsigned char *input = NULL; + int size = 0; + + input = reinterpret_cast + (malloc(sizeof(char) * value.length()+1)); + + if (input == NULL) { + return ""; } - return value; + + memcpy(input, value.c_str(), value.length()+1); + + size = inplace(input, value.length()); + + ret.assign(reinterpret_cast(input), size); + free(input); + + return ret; } + +int SqlHexDecode::inplace(unsigned char *data, int len) { + unsigned char *d, *begin = data; + + if ((data == NULL) || (len == 0)) { + return 0; + } + + for (d = data; *data; *d++ = *data++) { + if (*data != '0') { + continue; + } + ++data; + if (mytolower(*data) != 'x') { + data--; + continue; + } + + data++; + + // Do we need to keep "0x" if no hexa after? + if (!VALID_HEX(data[0]) || !VALID_HEX(data[1])) { + data -= 2; + continue; + } + + while (VALID_HEX(data[0]) && VALID_HEX(data[1])) { + *d++ = x2c(data); + data += 2; + } + } + + *d = '\0'; + return strlen(reinterpret_cast(begin)); +} + + + } // namespace transformations } // namespace actions } // namespace modsecurity diff --git a/src/actions/transformations/sql_hex_decode.h b/src/actions/transformations/sql_hex_decode.h index 02240c75..3284dcc6 100644 --- a/src/actions/transformations/sql_hex_decode.h +++ b/src/actions/transformations/sql_hex_decode.h @@ -30,10 +30,19 @@ namespace transformations { class SqlHexDecode : public Transformation { public: - explicit SqlHexDecode(std::string action); - std::string - evaluate(std::string exp, + explicit SqlHexDecode(std::string action) : Transformation(action) { } + + std::string evaluate(std::string exp, Transaction *transaction) override; + + static int inplace(unsigned char *data, int len); + + static int mytolower(int ch) { + if (ch >= 'A' && ch <= 'Z') + return ('a' + ch - 'A'); + else + return ch; + } }; } // namespace transformations diff --git a/src/actions/transformations/transformation.cc b/src/actions/transformations/transformation.cc index 761cbd54..9b06b7ac 100644 --- a/src/actions/transformations/transformation.cc +++ b/src/actions/transformations/transformation.cc @@ -105,7 +105,7 @@ Transformation* Transformation::instantiate(std::string a) { IF_MATCH(replaceComments) { return new ReplaceComments(a); } IF_MATCH(replaceNulls) { return new ReplaceNulls(a); } IF_MATCH(sha1) { return new Sha1(a); } - IF_MATCH(sql_hex_decode) { return new SqlHexDecode(a); } + IF_MATCH(sqlHexDecode) { return new SqlHexDecode(a); } IF_MATCH(transformation) { return new Transformation(a); } IF_MATCH(trimLeft) { return new TrimLeft(a); } IF_MATCH(trimRight) { return new TrimRight(a); } diff --git a/test/test-cases/secrules-language-tests b/test/test-cases/secrules-language-tests index ca597a23..002eb1e6 160000 --- a/test/test-cases/secrules-language-tests +++ b/test/test-cases/secrules-language-tests @@ -1 +1 @@ -Subproject commit ca597a23aa6eca03757c612543802fcdb884f135 +Subproject commit 002eb1e668b7a017eecfdfe9c5415fb9921c0be4