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
Closes #8749
This commit is contained in:
Daniel Stenberg 2022-04-25 13:05:40 +02:00
parent 8f2079154f
commit 6e65999395
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
2 changed files with 31 additions and 19 deletions

View File

@ -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;
@ -1905,10 +1917,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
@ -2084,6 +2093,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);

View File

@ -1329,14 +1329,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 */