From 6847c1fabaf3708a67e5b575a908c6cca42d432c Mon Sep 17 00:00:00 2001 From: wiaamm Date: Mon, 19 May 2025 17:40:23 +0300 Subject: [PATCH] fix waf tag to openappsec --- .../nginx_attachment/nginx_parser.cc | 45 ++++++++++++++++--- .../user_identifiers_config.cc | 43 +++++++++++++----- components/include/user_identifiers_config.h | 2 +- 3 files changed, 72 insertions(+), 18 deletions(-) diff --git a/components/attachment-intakers/nginx_attachment/nginx_parser.cc b/components/attachment-intakers/nginx_attachment/nginx_parser.cc index 7392e00..db33918 100755 --- a/components/attachment-intakers/nginx_attachment/nginx_parser.cc +++ b/components/attachment-intakers/nginx_attachment/nginx_parser.cc @@ -30,6 +30,7 @@ Buffer NginxParser::tenant_header_key = Buffer(); static const Buffer proxy_ip_header_key("X-Forwarded-For", 15, Buffer::MemoryType::STATIC); static const Buffer waf_tag_key("x-waf-tag", 9, Buffer::MemoryType::STATIC); static const Buffer source_ip("sourceip", 8, Buffer::MemoryType::STATIC); +bool is_keep_alive_ctx = getenv("SAAS_KEEP_ALIVE_HDR_NAME") != nullptr; map NginxParser::content_encodings = { {Buffer("identity"), CompressionType::NO_COMPRESSION}, @@ -178,22 +179,54 @@ getActivetenantAndProfile(const string &str, const string &deli = ",") } Maybe> -NginxParser::parseRequestHeaders(const Buffer &data) +NginxParser::parseRequestHeaders(const Buffer &data, const unordered_set &ignored_headers) { - auto parsed_headers = genHeaders(data); - if (!parsed_headers.ok()) return parsed_headers.passErr(); + auto maybe_parsed_headers = genHeaders(data); + if (!maybe_parsed_headers.ok()) return maybe_parsed_headers.passErr(); auto i_transaction_table = Singleton::Consume>::by(); + auto parsed_headers = maybe_parsed_headers.unpack(); + NginxAttachmentOpaque &opaque = i_transaction_table->getState(); - for (const HttpHeader &header : *parsed_headers) { + if (is_keep_alive_ctx || !ignored_headers.empty()) { + bool is_last_header_removed = false; + parsed_headers.erase( + remove_if( + parsed_headers.begin(), + parsed_headers.end(), + [&opaque, &is_last_header_removed, &ignored_headers](const HttpHeader &header) + { + string hdr_key = static_cast(header.getKey()); + string hdr_val = static_cast(header.getValue()); + if ( + opaque.setKeepAliveCtx(hdr_key, hdr_val) + || ignored_headers.find(hdr_key) != ignored_headers.end() + ) { + dbgTrace(D_NGINX_ATTACHMENT_PARSER) << "Header was removed from headers list: " << hdr_key; + if (header.isLastHeader()) { + dbgTrace(D_NGINX_ATTACHMENT_PARSER) << "Last header was removed from headers list"; + is_last_header_removed = true; + } + return true; + } + return false; + } + ), + parsed_headers.end() + ); + if (is_last_header_removed) { + dbgTrace(D_NGINX_ATTACHMENT_PARSER) << "Adjusting last header flag"; + if (!parsed_headers.empty()) parsed_headers.back().setIsLastHeader(); + } + } + + for (const HttpHeader &header : parsed_headers) { auto source_identifiers = getConfigurationWithDefault( UsersAllIdentifiersConfig(), "rulebase", "usersIdentifiers" ); source_identifiers.parseRequestHeaders(header); - - NginxAttachmentOpaque &opaque = i_transaction_table->getState(); opaque.addToSavedData( HttpTransactionData::req_headers, static_cast(header.getKey()) + ": " + static_cast(header.getValue()) + "\r\n" diff --git a/components/attachment-intakers/nginx_attachment/user_identifiers_config.cc b/components/attachment-intakers/nginx_attachment/user_identifiers_config.cc index 8a75e04..05694a5 100755 --- a/components/attachment-intakers/nginx_attachment/user_identifiers_config.cc +++ b/components/attachment-intakers/nginx_attachment/user_identifiers_config.cc @@ -282,21 +282,39 @@ isIpTrusted(const string &value, const vector &cidr_values) } Maybe -UsersAllIdentifiersConfig::parseXForwardedFor(const string &str) const +UsersAllIdentifiersConfig::parseXForwardedFor(const string &str, ExtractType type) const { vector header_values = split(str); - if (header_values.empty()) return genError("No IP found in the xff header list"); vector xff_values = getHeaderValuesFromConfig("x-forwarded-for"); vector cidr_values(xff_values.begin(), xff_values.end()); + string last_valid_ip; - for (const string &value : header_values) { - if (!IPAddr::createIPAddr(value).ok()) { - dbgWarning(D_NGINX_ATTACHMENT_PARSER) << "Invalid IP address found in the xff header IPs list: " << value; - return genError("Invalid IP address"); + for (auto it = header_values.rbegin(); it != header_values.rend() - 1; ++it) { + if (!IPAddr::createIPAddr(*it).ok()) { + dbgWarning(D_NGINX_ATTACHMENT_PARSER) << "Invalid IP address found in the xff header IPs list: " << *it; + if (last_valid_ip.empty()) { + return genError("Invalid IP address"); + } + return last_valid_ip; } - if (!isIpTrusted(value, cidr_values)) return genError("Untrusted Ip found"); + last_valid_ip = *it; + if (type == ExtractType::PROXYIP) continue; + if (!isIpTrusted(*it, cidr_values)) { + dbgDebug(D_NGINX_ATTACHMENT_PARSER) << "Found untrusted IP in the xff header IPs list: " << *it; + return *it; + } + } + + if (!IPAddr::createIPAddr(header_values[0]).ok()) { + dbgWarning(D_NGINX_ATTACHMENT_PARSER) + << "Invalid IP address found in the xff header IPs list: " + << header_values[0]; + if (last_valid_ip.empty()) { + return genError("No Valid Ip address was found"); + } + return last_valid_ip; } return header_values[0]; @@ -312,9 +330,7 @@ UsersAllIdentifiersConfig::setXFFValuesToOpaqueCtx(const HttpHeader &header, Ext return; } NginxAttachmentOpaque &opaque = i_transaction_table->getState(); - opaque.setSavedData(HttpTransactionData::xff_vals_ctx, header.getValue()); - dbgTrace(D_NGINX_ATTACHMENT_PARSER) << "xff found, value from header: " << static_cast(header.getValue()); - auto value = parseXForwardedFor(header.getValue()); + auto value = parseXForwardedFor(header.getValue(), type); if (!value.ok()) { dbgTrace(D_NGINX_ATTACHMENT_PARSER) << "Could not extract source identifier from X-Forwarded-For header"; return; @@ -323,8 +339,13 @@ UsersAllIdentifiersConfig::setXFFValuesToOpaqueCtx(const HttpHeader &header, Ext if (type == ExtractType::SOURCEIDENTIFIER) { opaque.setSourceIdentifier(header.getKey(), value.unpack()); dbgDebug(D_NGINX_ATTACHMENT_PARSER) - << "Added source identifir to XFF " + << "Added source identifier from XFF header" << value.unpack(); + opaque.setSavedData(HttpTransactionData::xff_vals_ctx, header.getValue()); + opaque.setSavedData(HttpTransactionData::source_identifier, value.unpack()); + dbgTrace(D_NGINX_ATTACHMENT_PARSER) + << "XFF found, set ctx with value from header: " + << static_cast(header.getValue()); } else { opaque.setSavedData(HttpTransactionData::proxy_ip_ctx, value.unpack()); } diff --git a/components/include/user_identifiers_config.h b/components/include/user_identifiers_config.h index aed9a3a..61ba320 100755 --- a/components/include/user_identifiers_config.h +++ b/components/include/user_identifiers_config.h @@ -59,7 +59,7 @@ private: const std::string::const_iterator &end, const std::string &key) const; Buffer extractKeyValueFromCookie(const std::string &cookie_value, const std::string &key) const; - Maybe parseXForwardedFor(const std::string &str) const; + Maybe parseXForwardedFor(const std::string &str, ExtractType type) const; std::vector user_identifiers; };