From 2be87227d4b4024c91ff6c856520cac9c9619555 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 25 Apr 2022 13:05:40 +0200 Subject: [PATCH 1/2] 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 Upstream-commit: 6e659993952aa5f90f48864be84a1bbb047fc258 Signed-off-by: Kamil Dudka --- lib/http.c | 33 +++++++++++++++++++++------------ lib/urldata.h | 16 +++++++++------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/lib/http.c b/lib/http.c index 799d4fb..0791dcf 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,15 +862,11 @@ 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 || - 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(data, conn, authhost, request, path, FALSE); - } else authhost->done = TRUE; @@ -1906,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 @@ -2081,6 +2089,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 03da59a..f92052a 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1336,14 +1336,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 */ -- 2.34.1 From c0d12f1634785596746e5d461319dcb95b5b6ae8 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 25 Apr 2022 13:05:47 +0200 Subject: [PATCH 2/2] test898: verify the fix for CVE-2022-27776 Do not pass on Authorization headers on redirects to another port Upstream-commit: afe752e0504ab60bf63787ede0b992cbe1065f78 Signed-off-by: Kamil Dudka --- tests/data/Makefile.inc | 2 +- tests/data/test898 | 90 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 tests/data/test898 diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index 59d46bc..7ae2cf8 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -106,7 +106,7 @@ test854 test855 test856 test857 test858 test859 test860 test861 test862 \ test863 test864 test865 test866 test867 test868 test869 test870 test871 \ test872 test873 test874 test875 test876 test877 test878 test879 test880 \ test881 test882 test883 test884 test885 test886 test887 test888 test889 \ -test890 test891 test892 test893 test894 test895 test896 \ +test890 test891 test892 test893 test894 test895 test896 test898 \ \ test900 test901 test902 test903 test904 test905 test906 test907 test908 \ test909 test910 test911 test912 test913 test914 test915 test916 test917 \ diff --git a/tests/data/test898 b/tests/data/test898 new file mode 100644 index 0000000..5cbb7d8 --- /dev/null +++ b/tests/data/test898 @@ -0,0 +1,90 @@ + + + +HTTP +--location +Authorization +Cookie + + + +# +# Server-side + + +HTTP/1.1 301 redirect +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Content-Length: 0 +Connection: close +Content-Type: text/html +Location: http://firsthost.com:9999/a/path/%TESTNUMBER0002 + + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Content-Length: 4 +Connection: close +Content-Type: text/html + +hey + + + +HTTP/1.1 301 redirect +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Content-Length: 0 +Connection: close +Content-Type: text/html +Location: http://firsthost.com:9999/a/path/%TESTNUMBER0002 + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Content-Length: 4 +Connection: close +Content-Type: text/html + +hey + + + + +# +# Client-side + + +http + + +HTTP with custom auth and cookies redirected to HTTP on a diff port + + +-x http://%HOSTIP:%HTTPPORT http://firsthost.com -L -H "Authorization: Basic am9lOnNlY3JldA==" -H "Cookie: userpwd=am9lOnNlY3JldA==" + + + +# +# Verify data after the test has been "shot" + + +GET http://firsthost.com/ HTTP/1.1 +Host: firsthost.com +User-Agent: curl/%VERSION +Accept: */* +Proxy-Connection: Keep-Alive +Authorization: Basic am9lOnNlY3JldA== +Cookie: userpwd=am9lOnNlY3JldA== + +GET http://firsthost.com:9999/a/path/%TESTNUMBER0002 HTTP/1.1 +Host: firsthost.com:9999 +User-Agent: curl/%VERSION +Accept: */* +Proxy-Connection: Keep-Alive + + + + -- 2.34.1