104 lines
4.2 KiB
Diff
104 lines
4.2 KiB
Diff
From 125302094326ad5eb0ea87f2d2ece6ceab1b1e59 Mon Sep 17 00:00:00 2001
|
|
From: Daniel Stenberg <daniel@haxx.se>
|
|
Date: Fri, 22 Apr 2022 08:19:18 +0200
|
|
Subject: [PATCH] http: avoid auth/cookie on redirects same host diff port
|
|
|
|
CVE-2022-27776
|
|
|
|
Reported-by: Harry Sintonen
|
|
Bug: https://curl.se/docs/CVE-2022-27776.html
|
|
diff --git a/lib/http.c b/lib/http.c
|
|
index c232ed4..7ccc5b5 100644
|
|
--- a/lib/http.c
|
|
+++ b/lib/http.c
|
|
@@ -751,6 +751,21 @@ output_auth_headers(struct connectdata *conn,
|
|
return CURLE_OK;
|
|
}
|
|
|
|
+/*
|
|
+ * allow_auth_to_host() tells if autentication, cookies or other "sensitive
|
|
+ * data" can (still) be sent to this host.
|
|
+ */
|
|
+static bool allow_auth_to_host(struct Curl_easy *data)
|
|
+{
|
|
+ struct connectdata *conn = data->conn;
|
|
+ return (!data->state.this_is_a_follow ||
|
|
+ data->set.allow_auth_to_other_hosts ||
|
|
+ (data->state.first_host &&
|
|
+ strcasecompare(data->state.first_host, conn->host.name) &&
|
|
+ (data->state.first_remote_port == conn->remote_port) &&
|
|
+ (data->state.first_remote_protocol == conn->handler->protocol)));
|
|
+}
|
|
+
|
|
/**
|
|
* Curl_http_output_auth() setups the authentication headers for the
|
|
* host/proxy and the correct authentication
|
|
@@ -822,15 +837,12 @@ Curl_http_output_auth(struct connectdata *conn,
|
|
with it */
|
|
authproxy->done = TRUE;
|
|
|
|
- /* To prevent the user+password to get sent to other than the original
|
|
- host due to a location-follow, we do some weirdo checks here */
|
|
- if(!data->state.this_is_a_follow ||
|
|
- conn->bits.netrc ||
|
|
- !data->state.first_host ||
|
|
- data->set.allow_auth_to_other_hosts ||
|
|
- strcasecompare(data->state.first_host, conn->host.name)) {
|
|
+ /* To prevent the user+password to get sent to other than the original host
|
|
+ due to a location-follow */
|
|
+ if(allow_auth_to_host(data)
|
|
+ || conn->bits.netrc
|
|
+ )
|
|
result = output_auth_headers(conn, authhost, request, path, FALSE);
|
|
- }
|
|
else
|
|
authhost->done = TRUE;
|
|
|
|
@@ -1802,10 +1814,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
|
|
checkprefix("Cookie:", compare)) &&
|
|
/* be careful of sending this potentially sensitive header to
|
|
other hosts */
|
|
- (data->state.this_is_a_follow &&
|
|
- data->state.first_host &&
|
|
- !data->set.allow_auth_to_other_hosts &&
|
|
- !strcasecompare(data->state.first_host, conn->host.name)))
|
|
+ !allow_auth_to_host(data))
|
|
;
|
|
else {
|
|
result = Curl_dyn_addf(req, "%s\r\n", compare);
|
|
@@ -1989,6 +1998,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|
return CURLE_OUT_OF_MEMORY;
|
|
|
|
data->state.first_remote_port = conn->remote_port;
|
|
+ data->state.first_remote_protocol = conn->handler->protocol;
|
|
}
|
|
|
|
if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
|
|
diff --git a/lib/urldata.h b/lib/urldata.h
|
|
index a71ce08..4f434f3 100644
|
|
--- a/lib/urldata.h
|
|
+++ b/lib/urldata.h
|
|
@@ -1332,13 +1332,15 @@ struct UrlState {
|
|
char *ulbuf; /* allocated upload buffer or NULL */
|
|
curl_off_t current_speed; /* the ProgressShow() function sets this,
|
|
bytes / second */
|
|
- char *first_host; /* host name of the first (not followed) request.
|
|
- if set, this should be the host name that we will
|
|
- sent authorization to, no else. Used to make Location:
|
|
- following not keep sending user+password... This is
|
|
- strdup() data.
|
|
- */
|
|
- int first_remote_port; /* remote port of the first (not followed) request */
|
|
+
|
|
+ /* host name, port number and protocol of the first (not followed) request.
|
|
+ if set, this should be the host name that we will sent authorization to,
|
|
+ no else. Used to make Location: following not keep sending user+password.
|
|
+ This is strdup()ed data. */
|
|
+ char *first_host;
|
|
+ int first_remote_port;
|
|
+ unsigned int first_remote_protocol;
|
|
+
|
|
struct curl_ssl_session *session; /* array of 'max_ssl_sessions' size */
|
|
long sessionage; /* number of the most recent session */
|
|
unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */
|