|
|
e2987f |
From 9f7136105bff920413042a8806cc5de3f6086d6d Mon Sep 17 00:00:00 2001
|
|
|
e2987f |
From: Thomas Leroy <32497783+p4zuu@users.noreply.github.com>
|
|
|
e2987f |
Date: Tue, 28 Nov 2023 07:35:46 +0000
|
|
|
e2987f |
Subject: [PATCH] Limit the number of allowed X-Forwarded-For hops (#1589)
|
|
|
e2987f |
|
|
|
e2987f |
Squid will ignore all X-Forwarded-For elements listed after the first 64
|
|
|
e2987f |
addresses allowed by the follow_x_forwarded_for directive. A different
|
|
|
e2987f |
limit can be specified by defining a C++ SQUID_X_FORWARDED_FOR_HOP_MAX
|
|
|
e2987f |
macro, but that macro is not a supported Squid configuration interface
|
|
|
e2987f |
and may change or disappear at any time.
|
|
|
e2987f |
|
|
|
e2987f |
Squid will log a cache.log ERROR if the hop limit has been reached.
|
|
|
e2987f |
|
|
|
e2987f |
This change works around problematic ACLChecklist and/or slow ACLs
|
|
|
e2987f |
implementation that results in immediate nonBlockingCheck() callbacks.
|
|
|
e2987f |
Such callbacks have caused many bugs and development complications. In
|
|
|
e2987f |
clientFollowXForwardedForCheck() context, they lead to indirect
|
|
|
e2987f |
recursion that was bound only by the number of allowed XFF entries,
|
|
|
e2987f |
which could reach thousands and exhaust Squid process call stack.
|
|
|
e2987f |
|
|
|
e2987f |
This recursion bug was discovered and detailed by Joshua Rogers at
|
|
|
e2987f |
https://megamansec.github.io/Squid-Security-Audit/xff-stackoverflow.html
|
|
|
e2987f |
where it was filed as "X-Forwarded-For Stack Overflow".
|
|
|
e2987f |
---
|
|
|
e2987f |
src/ClientRequestContext.h | 4 ++++
|
|
|
e2987f |
src/client_side_request.cc | 17 +++++++++++++++--
|
|
|
e2987f |
2 files changed, 19 insertions(+), 2 deletions(-)
|
|
|
e2987f |
|
|
|
e2987f |
diff --git a/src/ClientRequestContext.h b/src/ClientRequestContext.h
|
|
|
e2987f |
index 7dde9bc..775e308 100644
|
|
|
e2987f |
--- a/src/ClientRequestContext.h
|
|
|
e2987f |
+++ b/src/ClientRequestContext.h
|
|
|
e2987f |
@@ -90,6 +90,10 @@ public:
|
|
|
e2987f |
ErrorState *error; ///< saved error page for centralized/delayed processing
|
|
|
e2987f |
bool readNextRequest; ///< whether Squid should read after error handling
|
|
|
e2987f |
|
|
|
e2987f |
+#if FOLLOW_X_FORWARDED_FOR
|
|
|
e2987f |
+ size_t currentXffHopNumber = 0; ///< number of X-Forwarded-For header values processed so far
|
|
|
e2987f |
+#endif
|
|
|
e2987f |
+
|
|
|
e2987f |
private:
|
|
|
e2987f |
CBDATA_CLASS2(ClientRequestContext);
|
|
|
e2987f |
};
|
|
|
e2987f |
diff --git a/src/client_side_request.cc b/src/client_side_request.cc
|
|
|
e2987f |
index 57d8975..9b77271 100644
|
|
|
e2987f |
--- a/src/client_side_request.cc
|
|
|
e2987f |
+++ b/src/client_side_request.cc
|
|
|
e2987f |
@@ -362,6 +362,11 @@ clientBeginRequest(const HttpRequestMethod& method, char const *url, CSCB * stre
|
|
|
e2987f |
request->client_addr.setNoAddr();
|
|
|
e2987f |
|
|
|
e2987f |
#if FOLLOW_X_FORWARDED_FOR
|
|
|
e2987f |
+
|
|
|
e2987f |
+#if !defined(SQUID_X_FORWARDED_FOR_HOP_MAX)
|
|
|
e2987f |
+#define SQUID_X_FORWARDED_FOR_HOP_MAX 64
|
|
|
e2987f |
+#endif
|
|
|
e2987f |
+
|
|
|
e2987f |
request->indirect_client_addr.setNoAddr();
|
|
|
e2987f |
#endif /* FOLLOW_X_FORWARDED_FOR */
|
|
|
e2987f |
|
|
|
e2987f |
@@ -475,8 +480,15 @@ clientFollowXForwardedForCheck(allow_t answer, void *data)
|
|
|
e2987f |
/* override the default src_addr tested if we have to go deeper than one level into XFF */
|
|
|
e2987f |
Filled(calloutContext->acl_checklist)->src_addr = request->indirect_client_addr;
|
|
|
e2987f |
}
|
|
|
e2987f |
- calloutContext->acl_checklist->nonBlockingCheck(clientFollowXForwardedForCheck, data);
|
|
|
e2987f |
- return;
|
|
|
e2987f |
+ if (++calloutContext->currentXffHopNumber < SQUID_X_FORWARDED_FOR_HOP_MAX) {
|
|
|
e2987f |
+ calloutContext->acl_checklist->nonBlockingCheck(clientFollowXForwardedForCheck, data);
|
|
|
e2987f |
+ return;
|
|
|
e2987f |
+ }
|
|
|
e2987f |
+ debugs(28, DBG_CRITICAL, "ERROR: Ignoring trailing X-Forwarded-For addresses" <<
|
|
|
e2987f |
+ Debug::Extra << "addresses allowed by follow_x_forwarded_for: " << calloutContext->currentXffHopNumber <<
|
|
|
e2987f |
+ Debug::Extra << "last/accepted address: " << request->indirect_client_addr <<
|
|
|
e2987f |
+ Debug::Extra << "ignored trailing addresses: " << request->x_forwarded_for_iterator);
|
|
|
e2987f |
+ // fall through to resume clientAccessCheck() processing
|
|
|
e2987f |
}
|
|
|
e2987f |
} /*if (answer == ACCESS_ALLOWED &&
|
|
|
e2987f |
request->x_forwarded_for_iterator.size () != 0)*/
|
|
|
e2987f |
--
|
|
|
e2987f |
2.43.0
|
|
|
e2987f |
|