diff --git a/headers/modsecurity/assay.h b/headers/modsecurity/assay.h index b59d6eea..52fed4ae 100644 --- a/headers/modsecurity/assay.h +++ b/headers/modsecurity/assay.h @@ -169,6 +169,7 @@ class Assay { int m_clientPort; int m_serverPort; const char *m_uri; + std::string m_uri_decoded; const char *m_protocol; const char *m_httpVersion; diff --git a/src/assay.cc b/src/assay.cc index 8c8ca566..c4175b60 100644 --- a/src/assay.cc +++ b/src/assay.cc @@ -185,8 +185,9 @@ int Assay::processURI(const char *uri, const char *protocol, m_protocol = protocol; m_httpVersion = http_version; m_uri = uri; + m_uri_decoded = uri_decode(uri); - const char *pos = strchr(uri, '?'); + const char *pos = strchr(m_uri_decoded.c_str(), '?'); if (pos != NULL && strlen(pos) > 2) { /** @@ -359,10 +360,13 @@ int Assay::processRequestBody() { * the secrules said about it. * */ - std::string content = m_requestBody.str(); - char sep1 = '&'; + std::string content = uri_decode(m_requestBody.str()); + content.erase(content.length()-1, 1); - std::vector key_value = split(content, sep1); + char sep1 = '&'; + const char *pos = strchr(content.c_str(), '?'); + + std::vector key_value = split(content.c_str(), sep1); for (std::string t : key_value) { /** @@ -999,6 +1003,7 @@ std::string Assay::to_json(int parts) { return log; } + void Assay::store_variable(std::string key, std::string value) { this->m_variables_strings.emplace(key, value); } diff --git a/src/utils.cc b/src/utils.cc index 5489ce86..95905e0d 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -23,6 +23,10 @@ #include #include #include +#include +#include +#include + #if defined _MSC_VER #include @@ -78,6 +82,100 @@ std::string ascTime(time_t *t) { } +void chomp(std::string *str) { + std::string::size_type pos = str->find_last_not_of("\n\t"); + if (pos != std::string::npos) { + str->erase(pos+1, str->length()-pos-1); + } +} + + +const char SAFE[256] = { + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 2 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 3 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + + /* 4 */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 5 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + /* 6 */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 7 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + + /* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* A */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* B */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + /* C */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* D */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* E */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + +const char HEX2DEC[256] = { + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /* 0 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* 1 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* 2 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + + /* 4 */ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* 5 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* 6 */ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* 7 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + + /* 8 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* 9 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* A */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* B */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + + /* C */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* D */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* E */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + /* F */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + + +std::string uri_decode(const std::string & sSrc) { + // Note from RFC1630: "Sequences which start with a percent + // sign but are not followed by two hexadecimal characters + // (0-9, A-F) are reserved for future extension" + + const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); + const int SRC_LEN = sSrc.length(); + const unsigned char * const SRC_END = pSrc + SRC_LEN; + // last decodable '%' + const unsigned char * const SRC_LAST_DEC = SRC_END - 2; + + char * const pStart = new char[SRC_LEN]; + char * pEnd = pStart; + + while (pSrc < SRC_LAST_DEC) { + if (*pSrc == '%') { + char dec1, dec2; + if (-1 != (dec1 = HEX2DEC[*(pSrc + 1)]) + && -1 != (dec2 = HEX2DEC[*(pSrc + 2)])) { + *pEnd++ = (dec1 << 4) + dec2; + pSrc += 3; + continue; + } + } + *pEnd++ = *pSrc++; + } + + // the last 2- chars + while (pSrc < SRC_END) { + *pEnd++ = *pSrc++; + } + + std::string sResult(pStart, pEnd); + delete [] pStart; + return sResult; +} + + void createDir(std::string dir, int mode) { #if defined _MSC_VER _mkdir(dir.data()); diff --git a/src/utils.h b/src/utils.h index 2967ade6..68b8b0e0 100644 --- a/src/utils.h +++ b/src/utils.h @@ -29,6 +29,8 @@ namespace ModSecurity { std::string ascTime(time_t *t); void createDir(std::string dir, int mode); std::string dash_if_empty(const std::string& str); + void chomp(std::string *str); + std::string uri_decode(const std::string & sSrc); } // namespace ModSecurity #define SRC_UTILS_H_