commit 84de595fed3849792e4a4f234d75af0656c23841 Author: Daniel Stenberg Date: Mon Apr 25 13:05:40 2022 +0200 [Backport] http: avoid auth/cookie on redirects same host diff port Offering: RTOS CVE: CVE-2022-27776 Reference: upstream_commit_id=6e659993952aa5f90f48864be84a1bbb047fc258 DTS/AR: DTS2022042805098 type: LTS reason: fix CVE-2022-27776 for curl. weblink:https://github.com/curl/curl/commit/6e659993952aa5f90f48864be84a1bbb047fc258 CVE-2022-27776 Reported-by: Harry Sintonen Bug: https://curl.se/docs/CVE-2022-27776.html Closes #8749 Signed-off-by: lvshengyuan diff --git a/lib/http.c b/lib/http.c index 05b971b20..180edaf4b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -775,6 +775,21 @@ output_auth_headers(struct Curl_easy *data, 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 @@ -847,17 +862,14 @@ Curl_http_output_auth(struct Curl_easy *data, 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 || + /* 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) #ifndef CURL_DISABLE_NETRC - conn->bits.netrc || + || conn->bits.netrc #endif - !data->state.first_host || - data->set.allow_auth_to_other_hosts || - strcasecompare(data->state.first_host, conn->host.name)) { + ) result = output_auth_headers(data, conn, authhost, request, path, FALSE); - } else authhost->done = TRUE; @@ -1913,10 +1925,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, 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 { #ifdef USE_HYPER @@ -2088,6 +2097,7 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn) return CURLE_OUT_OF_MEMORY; data->state.first_remote_port = conn->remote_port; + data->state.first_remote_protocol = conn->handler->protocol; } Curl_safefree(data->state.aptr.host); diff --git a/lib/urldata.h b/lib/urldata.h index d3f337638..ffbe56993 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1324,14 +1324,16 @@ 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. - */ + + /* 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; + int retrycount; /* number of retries on a new connection */ - int first_remote_port; /* remote port of the first (not followed) request */ struct Curl_ssl_session *session; /* array of 'max_ssl_sessions' size */ long sessionage; /* number of the most recent session */ struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */