From bb0714e4cb9b453929e54b03f6f4cdc662a9be7d Mon Sep 17 00:00:00 2001 From: Ned Wright Date: Wed, 18 Jan 2023 16:36:27 +0000 Subject: [PATCH] Jan 18th update --- .../waap/waap_clib/DeepParser.cc | 56 +- .../security_apps/waap/waap_clib/Waf2Util.cc | 478 +++++++++++++----- .../security_apps/waap/waap_clib/Waf2Util.h | 15 + .../security_apps/waap/waap_component_impl.cc | 4 +- .../cpnano_base64/cpnano_base64.strip | Bin 39136 -> 0 bytes .../services_sdk/resources/debug_flags.h | 1 + .../package/open-appsec-cloud-mgmt | 4 +- 7 files changed, 409 insertions(+), 149 deletions(-) delete mode 100755 core/encryptor/cpnano_base64/cpnano_base64.strip diff --git a/components/security_apps/waap/waap_clib/DeepParser.cc b/components/security_apps/waap/waap_clib/DeepParser.cc index d26d680..6861201 100755 --- a/components/security_apps/waap/waap_clib/DeepParser.cc +++ b/components/security_apps/waap/waap_clib/DeepParser.cc @@ -36,7 +36,7 @@ USE_DEBUG_FLAG(D_WAAP_ULIMITS); #define DONE_PARSING 0 #define FAILED_PARSING -1 #define CONTINUE_PARSING 1 -#define MAX_DEPTH 5 +#define MAX_DEPTH 7 DeepParser::DeepParser( std::shared_ptr pWaapAssetState, @@ -228,37 +228,49 @@ int DeepParser::onKv(const char* k, size_t k_len, const char* v, size_t v_len, i std::string cur_val = std::string(v, v_len); // Detect and decode potential base64 chunks in the value before further processing - int b64DecodedCount = 0; - int b64DeletedCount = 0; - std::string base64_decoded_val; - Waap::Util::b64Decode(cur_val, - b64DecodeChunk, - b64DecodedCount, - b64DeletedCount, - base64_decoded_val); - // Add #base64 prefix to param name only if at least one Base64 replacement was done - bool base64ParamFound = (b64DecodedCount > 0 || b64DeletedCount > 0); + bool base64ParamFound = false; + dbgTrace(D_WAAP_DEEP_PARSER) << " ===Processing potential base64==="; + std::string base64_decoded_val, base64_key; + base64_variants base64_status = Waap::Util::b64Test (cur_val, + base64_key, + base64_decoded_val); - if (base64ParamFound) { - dbgTrace(D_WAAP_DEEP_PARSER) - << "DeepParser::onKv(): base64 decoded " - << b64DecodedCount - << " replacements, " - << b64DeletedCount - << " deletions."; - // replace cur_val with new value where base64 pieces are decoded and/or deleted. + dbgTrace(D_WAAP_DEEP_PARSER) << " status = " << base64_status + << " key = " << base64_key + << " value = " << base64_decoded_val; + + switch (base64_status) { + case SINGLE_B64_CHUNK_CONVERT: cur_val = base64_decoded_val; + base64ParamFound = true; + break; + case KEY_VALUE_B64_PAIR: + // going deep with new pair in case value is not empty + if (base64_decoded_val.size() > 0) { + cur_val = base64_decoded_val; + base64ParamFound = true; + rc = onKv(base64_key.c_str(), base64_key.size(), cur_val.data(), cur_val.size(), flags); + dbgTrace(D_WAAP_DEEP_PARSER) << " rc = " << rc; + if (rc != CONTINUE_PARSING) { + return rc; + } + } + break; + case CONTINUE_AS_IS: + break; + default: + break; } - // cur_val is later passed through some filters (such as urldecode) before JSON, XML or HTML is detected/decoded - std::string orig_val = cur_val; - if (base64ParamFound) { dbgTrace(D_WAAP_DEEP_PARSER) << "DeepParser::onKv(): pushing #base64 prefix to the key."; m_key.push("#base64", 7, false); } + // cur_val is later passed through some filters (such as urldecode) before JSON, XML or HTML is detected/decoded + std::string orig_val = cur_val; + // Escape HTML entities such as   before running heuristic stats analyzer std::string cur_val_html_escaped = orig_val; cur_val_html_escaped.erase(escape_html(cur_val_html_escaped.begin(), cur_val_html_escaped.end()), diff --git a/components/security_apps/waap/waap_clib/Waf2Util.cc b/components/security_apps/waap/waap_clib/Waf2Util.cc index 4c2ab84..13a4bab 100755 --- a/components/security_apps/waap/waap_clib/Waf2Util.cc +++ b/components/security_apps/waap/waap_clib/Waf2Util.cc @@ -40,6 +40,7 @@ using namespace std; USE_DEBUG_FLAG(D_WAAP); USE_DEBUG_FLAG(D_WAAP_EVASIONS); +USE_DEBUG_FLAG(D_WAAP_BASE64); #define MIN_HEX_LENGTH 6 #define charToDigit(c) (c - '0') @@ -504,6 +505,8 @@ const char* g_htmlTags[] = { "h6" }; +static const string b64_prefix("base64,"); + const size_t g_htmlTagsCount = sizeof(g_htmlTags) / sizeof(g_htmlTags[0]); bool startsWithHtmlTagName(const char* text) { @@ -956,12 +959,11 @@ string filterUTF7(const string& text) { // 4. percent of non-printable characters (!isprint()) // in decoded data is less than 10% (statistical garbage detection). // Returns false above checks fail. -bool -b64DecodeChunk( - const string& value, - string::const_iterator it, - string::const_iterator end, - string& decoded) +bool decodeBase64Chunk( + const string& value, + string::const_iterator it, + string::const_iterator end, + string& decoded) { decoded.clear(); uint32_t acc = 0; @@ -969,15 +971,147 @@ b64DecodeChunk( int terminatorCharsSeen = 0; // whether '=' character was seen, and how many of them. uint32_t nonPrintableCharsCount = 0; - dbgTrace(D_WAAP) << "b64DecodeChunk: value='" << value << "' match='" << string(it, end) << "'"; + dbgTrace(D_WAAP) << "decodeBase64Chunk: value='" << value << "' match='" << string(it, end) << "'"; + + // The encoded data length (without the "base64," prefix) should be exactly divisible by 4 + // len % 4 is not 0 i.e. this is not base64 + if ((end - it) % 4 != 0) { + dbgTrace(D_WAAP_BASE64) << + "b64DecodeChunk: (leave as-is) because encoded data length should be exactly divisible by 4."; + return false; + } + + while (it != end) { + unsigned char c = *it; + + if (terminatorCharsSeen) { + // terminator characters must all be '=', until end of match. + if (c != '=') { + dbgTrace(D_WAAP_BASE64) << + "decodeBase64Chunk: (leave as-is) because terminator characters must all be '='," << + "until end of match."; + return false; + } + + // We should see 0, 1 or 2 (no more) terminator characters + terminatorCharsSeen++; + + if (terminatorCharsSeen > 2) { + dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: (leave as-is) because terminatorCharsSeen > 2"; + return false; + } + + // allow for more terminator characters + it++; + continue; + } + + unsigned char val = 0; + + if (c >= 'A' && c <= 'Z') { + val = c - 'A'; + } + else if (c >= 'a' && c <= 'z') { + val = c - 'a' + 26; + } + else if (isdigit(c)) { + val = c - '0' + 52; + } + else if (c == '+') { + val = 62; + } + else if (c == '/') { + val = 63; + } + else if (c == '=') { + // Start tracking terminator characters + terminatorCharsSeen++; + it++; + continue; + } + else { + dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: (leave as-is) because of non-base64 character ('" << + c << "', ASCII " << (unsigned int)c << ")"; + return false; // non-base64 character + } + + acc = (acc << 6) | val; + acc_bits += 6; + + if (acc_bits >= 8) { + int code = (acc >> (acc_bits - 8)) & 0xFF; + // only leave low "acc_bits-8" bits, clear all higher bits + uint32_t mask = ~(1 << (acc_bits - 8)); + acc &= mask; + acc_bits -= 8; + + // Count non-printable characters seen + if (!isprint(code)) { + nonPrintableCharsCount++; + } + + decoded += (char)code; + } + + it++; + } + + // end of encoded sequence decoded. + + dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: decoded.size=" << decoded.size() << + ", nonPrintableCharsCount=" << nonPrintableCharsCount << "; decoded='" << decoded << "'"; + + // Return success only if decoded.size>=5 and there are less than 10% of non-printable + // characters in output. + if (decoded.size() >= 5) { + if (nonPrintableCharsCount * 10 < decoded.size()) { + dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: (decode/replace) decoded.size=" << decoded.size() << + ", nonPrintableCharsCount=" << nonPrintableCharsCount << ": replacing with decoded data"; + } + else { + dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: (delete) because decoded.size=" << decoded.size() << + ", nonPrintableCharsCount=" << nonPrintableCharsCount; + decoded.clear(); + } + return true; // successfully decoded. Returns decoded data in "decoded" parameter + } + + // If decoded size is too small - leave the encoded value (return false) + decoded.clear(); // discard partial data + dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: (leave as-is) because decoded too small. decoded.size=" << + decoded.size() << + ", nonPrintableCharsCount=" << nonPrintableCharsCount; + return false; +} + +// Attempts to detect and validate base64 chunk. +// Value is the full value inside which potential base64-encoded chunk was found, +// it and end point to start and end of that chunk. +// Returns true if succesful (and fills the "decoded" string with decoded data). +// Success criterias: +// 0. encoded sequence covers the whole value (doesn't have any characters around it) +// 1. encoded sequence consist of base64 alphabet (may end with zero, one or two '=' characters') +// 2. length of encoded sequence is exactly divisible by 4. +// 3. length of decoded is minimum 5 characters. +// 4. percent of non-printable characters (!isprint()) +// in decoded data is less than 10% (statistical garbage detection). +// Returns false above checks fail. +bool +b64DecodeChunk( + const string& value, + string::const_iterator it, + string::const_iterator end, + string& decoded) +{ + + dbgTrace(D_WAAP_BASE64) << "b64DecodeChunk: value='" << value << "' match='" << string(it, end) << "'"; // skip "base64," prefix if the line is starting with it. - if (end - it >= 7 && - *it == 'b' && - *(it + 1) == 'a' && - *(it + 2) == 's' && - string(it, it + 7) == "base64,") { - it += 7; // skip the prefix + unsigned int len = end - it; + if (len >= b64_prefix.size() && + it[0] == 'b' && it[1] == 'a' && it[2] == 's' && it[3] == + 'e' && it[4] == '6' && it[5] == '4' && it[6] == ',') { + it = it + b64_prefix.size(); // skip the prefix } else { // If the base64 candidate match within value is surrounded by other dat @@ -986,119 +1120,12 @@ b64DecodeChunk( // Note that this purposedly doesn't include matches starting with "base64," // prefix: we do want those prefixed matches to be decoded! if (it != value.begin() || end != value.end()) { - dbgTrace(D_WAAP) << "b64DecodeChunk: (leave as-is) because match is surrounded by other data."; + dbgTrace(D_WAAP_BASE64) << "b64DecodeChunk: (leave as-is) because match is surrounded by other data."; return false; } } - // The encoded data length (without the "base64," prefix) should be exactly divisible by 4 - // to be considered valid base64. - if ((end - it) % 4 != 0) { - dbgTrace(D_WAAP) << - "b64DecodeChunk: (leave as-is) because encoded data length should be exactly divisible by 4."; - return false; - } - - while (it != end) { - unsigned char c = *it; - - if (terminatorCharsSeen) { - // terminator characters must all be '=', until end of match. - if (c != '=') { - dbgTrace(D_WAAP) << - "b64DecodeChunk: (leave as-is) because terminator characters must all be '=', until end of match."; - return false; - } - - // We should see 0, 1 or 2 (no more) terminator characters - terminatorCharsSeen++; - - if (terminatorCharsSeen > 2) { - dbgTrace(D_WAAP) << "b64DecodeChunk: (leave as-is) because terminatorCharsSeen > 2"; - return false; - } - - // allow for more terminator characters - it++; - continue; - } - - unsigned char val = 0; - - if (c >= 'A' && c <= 'Z') { - val = c - 'A'; - } - else if (c >= 'a' && c <= 'z') { - val = c - 'a' + 26; - } - else if (isdigit(c)) { - val = c - '0' + 52; - } - else if (c == '+') { - val = 62; - } - else if (c == '/') { - val = 63; - } - else if (c == '=') { - // Start tracking terminator characters - terminatorCharsSeen++; - it++; - continue; - } - else { - dbgTrace(D_WAAP) << "b64DecodeChunk: (leave as-is) because of non-base64 character ('" << c << - "', ASCII " << (unsigned int)c << ")"; - return false; // non-base64 character - } - - acc = (acc << 6) | val; - acc_bits += 6; - - if (acc_bits >= 8) { - int code = (acc >> (acc_bits - 8)) & 0xFF; - // only leave low "acc_bits-8" bits, clear all higher bits - uint32_t mask = ~(1 << (acc_bits - 8)); - acc &= mask; - acc_bits -= 8; - - // Count non-printable characters seen - if (!isprint(code)) { - nonPrintableCharsCount++; - } - - decoded += (char)code; - } - - it++; - } - - // end of encoded sequence decoded. - - dbgTrace(D_WAAP) << "b64DecodeChunk: decoded.size=" << decoded.size() << ", nonPrintableCharsCount=" << - nonPrintableCharsCount << "; decoded='" << decoded << "'"; - - // Return success only if decoded.size>=5 and there are less than 10% of non-printable - // characters in output. - if (decoded.size() >= 5) { - if (nonPrintableCharsCount * 10 < decoded.size()) { - dbgTrace(D_WAAP) << "b64DecodeChunk: (decode/replace) decoded.size=" << decoded.size() << - ", nonPrintableCharsCount=" << nonPrintableCharsCount << ": replacing with decoded data"; - } - else { - dbgTrace(D_WAAP) << "b64DecodeChunk: (delete) because decoded.size=" << decoded.size() << - ", nonPrintableCharsCount=" << nonPrintableCharsCount; - // If percentage of non-printable characters in decoded is high, filter them out to prevent false alarms. - decoded.clear(); - } - return true; // successfully decoded. Returns decoded data in "decoded" parameter - } - - // If decoded size is too small - leave the encoded value (return false) - decoded.clear(); // discard partial data - dbgTrace(D_WAAP) << "b64DecodeChunk: (leave as-is) because decoded too small. decoded.size=" << decoded.size() << - ", nonPrintableCharsCount=" << nonPrintableCharsCount; - return false; + return decodeBase64Chunk(value, it, end, decoded); } vector split(const string& s, char delim) { @@ -1115,7 +1142,7 @@ namespace Waap { namespace Util { #define B64_TRAILERCHAR '=' -static const string b64_prefix("base64,"); + static bool err = false; static const SingleRegex invalid_hex_evasion_re( @@ -1133,6 +1160,18 @@ static const SingleRegex csp_report_policy_re( err, "csp_report_policy" ); +static const SingleRegex base64_key_value_detector_re( + "^[^<>;&\\?|=\\s]+={1}\\s*.+", + err, + "base64_key_value"); +static const SingleRegex base64_key_detector_re( + "^[^<>;&\\?|=\\s]+={1}", + err, + "base64_key"); +static const SingleRegex base64_prefix_detector_re( + "data:\\S*;base64,\\S+|base64,\\S+", + err, + "base64_prefix"); static void b64TestChunk(const string &s, string::const_iterator chunkStart, @@ -1172,6 +1211,199 @@ static void b64TestChunk(const string &s, } } +bool detectBase64Chunk( + const string &s, + string::const_iterator &start, + string::const_iterator &end) +{ + dbgTrace(D_WAAP_BASE64) << " ===detectBase64Chunk===: starting with = '" << s << "'"; + string::const_iterator it = s.begin(); + + //detect "base64," prefix to start search after this + for (; it != s.end()-7; it++) { + if (it[0] == 'b' && it[1] == 'a' && it[2] == 's' && it[3] == + 'e' && it[4] == '6' && it[5] == '4' && it[6] == ',') { + it = it + 7; + dbgTrace(D_WAAP_BASE64) << " ===detectBase64Chunk===: prefix skipped = '" << *it << "'"; + break; + } + } + + //look for start of encoded string + dbgTrace(D_WAAP_BASE64) << " ===detectBase64Chunk===: B64 itself = '" << *it << "'"; + bool isB64AlphaChar = Waap::Util::isAlphaAsciiFast(*it) || isdigit(*it) || *it=='/' || *it=='+'; + + if (isB64AlphaChar) { + // start tracking potential b64 chunk - just check its size + dbgTrace(D_WAAP_BASE64) << " ===detectBase64Chunk===: isB64AlphaChar = true, '" << *it << "'"; + start = it; + end = s.end(); + if ((end - start) % 4 == 0) { + return true; + } + } + // non base64 before supposed chunk - will not process + return false; +} + +bool isBase64PrefixProcessingOK ( + const string &s, + string &value) +{ + string::const_iterator start, end; + bool retVal = false; + dbgTrace(D_WAAP_BASE64) << " ===isBase64PrefixProcessingOK===: before regex for prefix for string '" << s << "'"; + if (base64_prefix_detector_re.hasMatch(s)) { + dbgTrace(D_WAAP_BASE64) << " ===isBase64PrefixProcessingOK===: prefix detected on string '" << s << "'"; + if (detectBase64Chunk(s, start, end)) { + dbgTrace(D_WAAP_BASE64) << " ===isBase64PrefixProcessingOK===: chunk detected"; + if ((start != s.end()) && (end == s.end())) { + retVal = decodeBase64Chunk(s, start, end, value); + } + } + } + return retVal; +} + +base64_variants b64Test ( + const string &s, + string &key, + string &value) +{ + + key.clear(); + bool retVal; + + dbgTrace(D_WAAP_BASE64) << " ===b64Test===: string = " << s + << " key = " << key << " value = " << value; + // Minimal length + if (s.size() < 8) { + return CONTINUE_AS_IS; + } + dbgTrace(D_WAAP_BASE64) << " ===b64Test===: minimal lenght test passed"; + + std::string prefix_decoded_val; + string::const_iterator it = s.begin(); + + // 1st check if we have key candidate + if (base64_key_value_detector_re.hasMatch(s)) { + base64_stage state = BEFORE_EQUAL; + dbgTrace(D_WAAP_BASE64) << " ===b64Test===: testB64Key test passed - looking for key"; + for (; (it != s.end()) && (state != DONE) && (state != MISDETECT); ++it) { + switch(state) { + case BEFORE_EQUAL: + if (*it != '=') { + key += string(1, *it); + } else { + key += string(1, *it); + state = EQUAL; + } + break; + case EQUAL: + if (*it == '=') { + it = s.begin(); + state=MISDETECT; + continue; + } + if (*it == ' ') { + //skip whitespaces - we don't need them in key + continue; + } else { + state = DONE; + } + break; + case DONE: + continue; + default: + break; + } + + } + dbgTrace(D_WAAP_BASE64) << " ===b64Test===: detected key = " << key; + if (it == s.end() || state == MISDETECT) { + dbgTrace(D_WAAP_BASE64) << " ===b64Test===: detected *it = s.end()" << *it; + if (key.size() > 0) { + it = s.begin(); + key.clear(); + } + } else { + it--; + + dbgTrace(D_WAAP_BASE64) << " ===b64Test===: Key is OK *it = " << *it; + } + } + + dbgTrace(D_WAAP_BASE64) << " ===b64Test===: after processing key = '" << key << "'"; + bool found = isBase64PrefixProcessingOK(s, prefix_decoded_val); + dbgTrace(D_WAAP_BASE64) << " ===b64Test===: after prefix test found = " + << found << " new value is '" << prefix_decoded_val << "' - done"; + if (found) { + value = prefix_decoded_val; + if (key.empty()) { + return SINGLE_B64_CHUNK_CONVERT; + } else { + key.pop_back(); + return KEY_VALUE_B64_PAIR; + } + } + + string::const_iterator start = s.end(); + dbgTrace(D_WAAP_BASE64) << " ===b64Test===: B64 itself = " << *it << " ======="; + bool isB64AlphaChar = Waap::Util::isAlphaAsciiFast(*it) || isdigit(*it) || *it=='/' || *it=='+'; + if (isB64AlphaChar) { + // 1st char is potential b64, let's try to convert this + dbgTrace(D_WAAP_BASE64) << + " ===b64Test===: Start tracking potential b64 chunk = " << *it << " ======="; + start = it; + if ((s.end() - start) % 4 != 0) { + key.clear(); + value.clear(); + return CONTINUE_AS_IS;; + } + } + else { + dbgTrace(D_WAAP_BASE64) << + " ===b64Test===: Non base64 before supposed chunk - will not process = " << *it << " ======="; + return CONTINUE_AS_IS; + } + + if (start != s.end()) { + // key is not empty, it should be tested for correct format (i.e. key=b64val and not splittable) + // else leave it as is + dbgTrace(D_WAAP_BASE64) << " ===b64Test===:BEFORE TESTING KEY key = '" << key << "'"; + if (!key.empty()) { + if (!base64_key_detector_re.hasMatch(key)) { + dbgTrace(D_WAAP_BASE64) << " ===b64Test===: Key is NOT GOOD regex key = '" << key << "'"; + return CONTINUE_AS_IS; + } + // remove '=' as last char in key - we don't need it + key.pop_back(); + dbgTrace(D_WAAP_BASE64) << " ===b64Test===: FINAL key = '" << key << "'"; + } + retVal = decodeBase64Chunk(s, start, s.end(), value); + dbgTrace(D_WAAP_BASE64) << " ===b64Test===: After testing and conversion value = " + << value << "retVal = '" << retVal <<"'"; + if (!retVal) { + key.clear(); + value.clear(); + return CONTINUE_AS_IS; + } + dbgTrace(D_WAAP_BASE64) << " ===b64Test===: After tpassed retVal check = " + << value << "retVal = '" << retVal <<"'" << "key = '" << key << "'"; + if (key.empty()) { + return SINGLE_B64_CHUNK_CONVERT; + } else { + return KEY_VALUE_B64_PAIR; + } + + } else { + // There are symbols after base64 chunk - leave as is, may be it will be splitted no next step + key.clear(); + value.clear(); + return CONTINUE_AS_IS; + } +} + void b64Decode( const string &s, RegexSubCallback_f cb, diff --git a/components/security_apps/waap/waap_clib/Waf2Util.h b/components/security_apps/waap/waap_clib/Waf2Util.h index 22b76ae..009d1bf 100755 --- a/components/security_apps/waap/waap_clib/Waf2Util.h +++ b/components/security_apps/waap/waap_clib/Waf2Util.h @@ -32,6 +32,9 @@ #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +enum base64_variants {SINGLE_B64_CHUNK_CONVERT, KEY_VALUE_B64_PAIR, CONTINUE_AS_IS}; +enum base64_stage {BEFORE_EQUAL, EQUAL, DONE, MISDETECT}; + // This is portable version of stricmp(), which is non-standard function (not even in C). // Contrary to stricmp(), for a slight optimization, s2 is ASSUMED to be already in lowercase. // s1 can be in mixed case and is convetred using tolower() before comparing to s2. @@ -830,6 +833,13 @@ void unescapeUnicode(std::string &text); // Try to find and decode UTF7 chunks std::string filterUTF7(const std::string &text); +bool +decodeBase64Chunk( + const std::string &value, + std::string::const_iterator it, + std::string::const_iterator end, + std::string &decoded); + bool b64DecodeChunk( const std::string &value, @@ -855,6 +865,11 @@ namespace Util { int &deletedCount, std::string &outStr); + base64_variants b64Test ( + const std::string &s, + std::string &key, + std::string &value); + // The original stdlib implementation of isalpha() supports locale settings which we do not really need. // It is also proven to contribute to slow performance in some of the algorithms using it. // This function has reduced functionality compared to stdlib isalpha(), but is much faster. diff --git a/components/security_apps/waap/waap_component_impl.cc b/components/security_apps/waap/waap_component_impl.cc index fa0cedd..2d84415 100755 --- a/components/security_apps/waap/waap_component_impl.cc +++ b/components/security_apps/waap/waap_component_impl.cc @@ -89,8 +89,6 @@ WaapComponent::Impl::init(const std::string &waapDataFileName) reputationAggregator.init(); - waapStateTable = Singleton::Consume::by(); - bool success = waf2_proc_start(waapDataFileName); if (!success) { dbgWarning(D_WAAP) << "WAF2 engine FAILED to initialize (probably failed to load signatures). Aborting!"; @@ -103,6 +101,8 @@ WaapComponent::Impl::init(const std::string &waapDataFileName) I_StaticResourcesHandler *static_resources = Singleton::Consume::by(); static_resources->registerStaticResource("cp-ab.js", "/etc/cp/conf/waap/cp-ab.js"); static_resources->registerStaticResource("cp-csrf.js", "/etc/cp/conf/waap/cp-csrf.js"); + + waapStateTable = Singleton::Consume::by(); } // Called when component is shut down diff --git a/core/encryptor/cpnano_base64/cpnano_base64.strip b/core/encryptor/cpnano_base64/cpnano_base64.strip deleted file mode 100755 index ea3883571f70ceb747b4559707d78d674d478f9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39136 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