From 08763adb5ca73cf57c9a60e5ed0b67f6eee46944 Mon Sep 17 00:00:00 2001 From: eaglegai Date: Fri, 6 May 2022 20:08:56 +0800 Subject: [PATCH] fix CVE-2022-22576 CVE-2022-27774 CVE-2022-27775 CVE-2022-27776 --- backport-001-CVE-2022-27774.patch | 69 ++++++++++++++++ backport-002-CVE-2022-27774.patch | 80 ++++++++++++++++++ backport-CVE-2022-22576.patch | 129 ++++++++++++++++++++++++++++++ backport-CVE-2022-27775.patch | 33 ++++++++ backport-CVE-2022-27776.patch | 103 ++++++++++++++++++++++++ backport-pre-CVE-2022-27774.patch | 35 ++++++++ curl.spec | 14 +++- 7 files changed, 462 insertions(+), 1 deletion(-) create mode 100644 backport-001-CVE-2022-27774.patch create mode 100644 backport-002-CVE-2022-27774.patch create mode 100644 backport-CVE-2022-22576.patch create mode 100644 backport-CVE-2022-27775.patch create mode 100644 backport-CVE-2022-27776.patch create mode 100644 backport-pre-CVE-2022-27774.patch diff --git a/backport-001-CVE-2022-27774.patch b/backport-001-CVE-2022-27774.patch new file mode 100644 index 0000000..37df52f --- /dev/null +++ b/backport-001-CVE-2022-27774.patch @@ -0,0 +1,69 @@ +From 2b4afd8dd2132a0edd16acbe7c8d4d5c4fd06e61 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 19 Apr 2022 12:49:28 +0200 +Subject: [PATCH 2/3] transfer: redirects to other protocols or ports clear + auth + +... unless explicitly permitted. + +Bug: https://curl.se/docs/CVE-2022-27774.html +Reported-by: Harry Sintonen +diff --git a/lib/transfer.c b/lib/transfer.c +index b8c3bcb..967ac03 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -1645,10 +1645,53 @@ CURLcode Curl_follow(struct Curl_easy *data, + return CURLE_OUT_OF_MEMORY; + } + else { +- + uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0); + if(uc) + return Curl_uc_to_curlcode(uc); ++ ++ /* Clear auth if this redirects to a different port number or protocol, ++ unless permitted */ ++ if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) { ++ char *portnum; ++ int port; ++ bool clear = FALSE; ++ ++ uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum, ++ CURLU_DEFAULT_PORT); ++ if(uc) { ++ free(newurl); ++ return Curl_uc_to_curlcode(uc); ++ } ++ port = atoi(portnum); ++ free(portnum); ++ ++ if(port != data->info.conn_remote_port) { ++ infof(data, "Clear auth, redirects to port from %u to %u", ++ data->info.conn_remote_port, port); ++ clear = TRUE; ++ } ++ else { ++ char *scheme; ++ const struct Curl_handler *p; ++ uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0); ++ if(uc) { ++ free(newurl); ++ return Curl_uc_to_curlcode(uc); ++ } ++ ++ p = Curl_builtin_scheme(scheme); ++ if(p && (p->protocol != data->info.conn_protocol)) { ++ infof(data, "Clear auth, redirects scheme from %s to %s", ++ data->info.conn_scheme, scheme); ++ clear = TRUE; ++ } ++ free(scheme); ++ } ++ if(clear) { ++ Curl_safefree(data->set.str[STRING_USERNAME]); ++ Curl_safefree(data->set.str[STRING_PASSWORD]); ++ } ++ } + } + + if(type == FOLLOW_FAKE) { diff --git a/backport-002-CVE-2022-27774.patch b/backport-002-CVE-2022-27774.patch new file mode 100644 index 0000000..8f3f6dd --- /dev/null +++ b/backport-002-CVE-2022-27774.patch @@ -0,0 +1,80 @@ +From 139a54ed0a172adaaf1a78d6f4fff50b2c3f9e08 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 25 Apr 2022 17:59:15 +0200 +Subject: [PATCH] openssl: don't leak the SRP credentials in redirects either + +Follow-up to 620ea21410030 + +Reported-by: Harry Sintonen +Closes #8751 +--- + lib/http.c | 10 +++++----- + lib/http.h | 6 ++++++ + lib/vtls/openssl.c | 3 ++- + 3 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/lib/http.c b/lib/http.c +index f0476f3b9272..0d5c449bc72a 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -776,10 +776,10 @@ output_auth_headers(struct Curl_easy *data, + } + + /* +- * allow_auth_to_host() tells if autentication, cookies or other "sensitive +- * data" can (still) be sent to this host. ++ * Curl_allow_auth_to_host() tells if authentication, cookies or other ++ * "sensitive data" can (still) be sent to this host. + */ +-static bool allow_auth_to_host(struct Curl_easy *data) ++bool Curl_allow_auth_to_host(struct Curl_easy *data) + { + struct connectdata *conn = data->conn; + return (!data->state.this_is_a_follow || +@@ -864,7 +864,7 @@ Curl_http_output_auth(struct Curl_easy *data, + + /* 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) ++ if(Curl_allow_auth_to_host(data) + || conn->bits.netrc + ) + result = output_auth_headers(conn, authhost, request, path, FALSE); +@@ -1917,7 +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 */ +- !allow_auth_to_host(data)) ++ !Curl_allow_auth_to_host(data)) + ; + else { + result = Curl_dyn_addf(req, "%s\r\n", compare); +diff --git a/lib/http.h b/lib/http.h +index 0972261e63bd..c4ab3c22dec9 100644 +--- a/lib/http.h ++++ b/lib/http.h +@@ -364,4 +364,10 @@ Curl_http_output_auth(struct Curl_easy *data, + bool proxytunnel); /* TRUE if this is the request setting + up the proxy tunnel */ + ++/* ++ * Curl_allow_auth_to_host() tells if authentication, cookies or other ++ * "sensitive data" can (still) be sent to this host. ++ */ ++bool Curl_allow_auth_to_host(struct Curl_easy *data); ++ + #endif /* HEADER_CURL_HTTP_H */ +diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c +index 5d8e2d39d8e2..3722005d44e9 100644 +--- a/lib/vtls/openssl.c ++++ b/lib/vtls/openssl.c +@@ -2924,7 +2924,8 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, + #endif + + #ifdef USE_TLS_SRP +- if(ssl_authtype == CURL_TLSAUTH_SRP) { ++ if((ssl_authtype == CURL_TLSAUTH_SRP) && ++ Curl_allow_auth_to_host(data)) { + char * const ssl_username = SSL_SET_OPTION(username); + + infof(data, "Using TLS-SRP username: %s\n", ssl_username); diff --git a/backport-CVE-2022-22576.patch b/backport-CVE-2022-22576.patch new file mode 100644 index 0000000..0c4922d --- /dev/null +++ b/backport-CVE-2022-22576.patch @@ -0,0 +1,129 @@ +From e193f712be95dc9e5e2b92eae6381d4572231152 Mon Sep 17 00:00:00 2001 +From: Patrick Monnerat +Date: Sun, 17 Apr 2022 23:29:46 +0200 +Subject: [PATCH] url: check sasl additional parameters for connection reuse. + +Also move static function safecmp() as non-static Curl_safecmp() since +its purpose is needed at several places. + +Bug: https://curl.se/docs/CVE-2022-22576.html + +CVE-2022-22576 +diff --git a/lib/strcase.c b/lib/strcase.c +index 955e3c7..cd04f2c 100644 +--- a/lib/strcase.c ++++ b/lib/strcase.c +@@ -251,6 +251,16 @@ void Curl_strntolower(char *dest, const char *src, size_t n) + } while(*src++ && --n); + } + ++/* Compare case-sensitive NUL-terminated strings, taking care of possible ++ * null pointers. Return true if arguments match. ++ */ ++bool Curl_safecmp(char *a, char *b) ++{ ++ if(a && b) ++ return !strcmp(a, b); ++ return !a && !b; ++} ++ + /* --- public functions --- */ + + int curl_strequal(const char *first, const char *second) +diff --git a/lib/strcase.h b/lib/strcase.h +index 10dc698..127bfdd 100644 +--- a/lib/strcase.h ++++ b/lib/strcase.h +@@ -48,4 +48,6 @@ char Curl_raw_toupper(char in); + void Curl_strntoupper(char *dest, const char *src, size_t n); + void Curl_strntolower(char *dest, const char *src, size_t n); + ++bool Curl_safecmp(char *a, char *b); ++ + #endif /* HEADER_CURL_STRCASE_H */ +diff --git a/lib/url.c b/lib/url.c +index a6519be..a8e2e41 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -752,6 +752,7 @@ static void conn_free(struct connectdata *conn) + Curl_safefree(conn->passwd); + Curl_safefree(conn->sasl_authzid); + Curl_safefree(conn->options); ++ Curl_safefree(conn->oauth_bearer); + Curl_dyn_free(&conn->trailer); + Curl_safefree(conn->host.rawalloc); /* host name buffer */ + Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */ +@@ -1284,7 +1285,9 @@ ConnectionExists(struct Curl_easy *data, + /* This protocol requires credentials per connection, + so verify that we're using the same name and password as well */ + if(strcmp(needle->user, check->user) || +- strcmp(needle->passwd, check->passwd)) { ++ strcmp(needle->passwd, check->passwd) || ++ !Curl_safecmp(needle->sasl_authzid, check->sasl_authzid) || ++ !Curl_safecmp(needle->oauth_bearer, check->oauth_bearer)) { + /* one of them was different */ + continue; + } +@@ -3486,6 +3489,14 @@ static CURLcode create_conn(struct Curl_easy *data, + } + } + ++ if(data->set.str[STRING_BEARER]) { ++ conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]); ++ if(!conn->oauth_bearer) { ++ result = CURLE_OUT_OF_MEMORY; ++ goto out; ++ } ++ } ++ + #ifdef USE_UNIX_SOCKETS + if(data->set.str[STRING_UNIX_SOCKET_PATH]) { + conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]); +diff --git a/lib/urldata.h b/lib/urldata.h +index abd8110..11d7a33 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -967,6 +967,7 @@ struct connectdata { + char *options; /* options string, allocated */ + + char *sasl_authzid; /* authorisation identity string, allocated */ ++ char *oauth_bearer; /* OAUTH2 bearer, allocated */ + + int httpversion; /* the HTTP version*10 reported by the server */ + int rtspversion; /* the RTSP version*10 reported by the server */ +diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c +index 62239be..c074605 100644 +--- a/lib/vtls/vtls.c ++++ b/lib/vtls/vtls.c +@@ -121,14 +121,6 @@ static bool blobcmp(struct curl_blob *first, struct curl_blob *second) + return !memcmp(first->data, second->data, first->len); /* same data */ + } + +-static bool safecmp(char *a, char *b) +-{ +- if(a && b) +- return !strcmp(a, b); +- else if(!a && !b) +- return TRUE; /* match */ +- return FALSE; /* no match */ +-} + + bool + Curl_ssl_config_matches(struct ssl_primary_config *data, +@@ -142,11 +133,11 @@ Curl_ssl_config_matches(struct ssl_primary_config *data, + (data->verifystatus == needle->verifystatus) && + blobcmp(data->cert_blob, needle->cert_blob) && + blobcmp(data->issuercert_blob, needle->issuercert_blob) && +- safecmp(data->CApath, needle->CApath) && +- safecmp(data->CAfile, needle->CAfile) && +- safecmp(data->clientcert, needle->clientcert) && +- safecmp(data->random_file, needle->random_file) && +- safecmp(data->egdsocket, needle->egdsocket) && ++ Curl_safecmp(data->CApath, needle->CApath) && ++ Curl_safecmp(data->CAfile, needle->CAfile) && ++ Curl_safecmp(data->clientcert, needle->clientcert) && ++ Curl_safecmp(data->random_file, needle->random_file) && ++ Curl_safecmp(data->egdsocket, needle->egdsocket) && + Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) && + Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) && + Curl_safe_strcasecompare(data->pinned_key, needle->pinned_key)) diff --git a/backport-CVE-2022-27775.patch b/backport-CVE-2022-27775.patch new file mode 100644 index 0000000..d349cdb --- /dev/null +++ b/backport-CVE-2022-27775.patch @@ -0,0 +1,33 @@ +From 46091487fbdb37ffbe9c495de86c62d14634b71a Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 21 Apr 2022 12:30:34 +0200 +Subject: [PATCH] conncache: include the zone id in the "bundle" hashkey + +Make connections to two separate IPv6 zone ids create separate +connections. + +Reported-by: Harry Sintonen +Bug: https://curl.se/docs/CVE-2022-27775.html +--- + lib/conncache.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +Index: curl-7.74.0/lib/conncache.c +=================================================================== +--- curl-7.74.0.orig/lib/conncache.c ++++ curl-7.74.0/lib/conncache.c +@@ -159,8 +159,12 @@ static void hashkey(struct connectdata * + /* report back which name we used */ + *hostp = hostname; + +- /* put the number first so that the hostname gets cut off if too long */ +- msnprintf(buf, len, "%ld%s", port, hostname); ++ /* put the numbers first so that the hostname gets cut off if too long */ ++#ifdef ENABLE_IPV6 ++ msnprintf(buf, len, "%u/%ld/%s", conn->scope_id, port, hostname); ++#else ++ msnprintf(buf, len, "%ld/%s", port, hostname); ++#endif + } + + /* Returns number of connections currently held in the connection cache. diff --git a/backport-CVE-2022-27776.patch b/backport-CVE-2022-27776.patch new file mode 100644 index 0000000..e96b9eb --- /dev/null +++ b/backport-CVE-2022-27776.patch @@ -0,0 +1,103 @@ +From 125302094326ad5eb0ea87f2d2ece6ceab1b1e59 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +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 */ diff --git a/backport-pre-CVE-2022-27774.patch b/backport-pre-CVE-2022-27774.patch new file mode 100644 index 0000000..0f74538 --- /dev/null +++ b/backport-pre-CVE-2022-27774.patch @@ -0,0 +1,35 @@ +From b92ebe53f3fc7b4a4355724a22690fdef4f1bf2f Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 19 Apr 2022 12:49:28 +0200 +Subject: [PATCH 1/3] connect: store "conn_remote_port" in the info struct + +To make it available after the connection ended. +diff --git a/lib/connect.c b/lib/connect.c +index e65d24d..0f122ce 100644 +--- a/lib/connect.c ++++ b/lib/connect.c +@@ -611,6 +611,7 @@ void Curl_persistconninfo(struct connectdata *conn) + conn->data->info.conn_scheme = conn->handler->scheme; + conn->data->info.conn_protocol = conn->handler->protocol; + conn->data->info.conn_primary_port = conn->primary_port; ++ conn->data->info.conn_remote_port = conn->remote_port; + conn->data->info.conn_local_port = conn->local_port; + } + +diff --git a/lib/urldata.h b/lib/urldata.h +index 11d7a33..a71ce08 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1145,7 +1145,11 @@ struct PureInfo { + reused, in the connection cache. */ + + char conn_primary_ip[MAX_IPADR_LEN]; +- long conn_primary_port; ++ int conn_primary_port; /* this is the destination port to the connection, ++ which might have been a proxy */ ++ int conn_remote_port; /* this is the "remote port", which is the port ++ number of the used URL, independent of proxy or ++ not */ + char conn_local_ip[MAX_IPADR_LEN]; + long conn_local_port; + const char *conn_scheme; diff --git a/curl.spec b/curl.spec index 354ef22..f90fae0 100644 --- a/curl.spec +++ b/curl.spec @@ -6,7 +6,7 @@ Name: curl Version: 7.71.1 -Release: 12 +Release: 13 Summary: Curl is used in command lines or scripts to transfer data License: MIT URL: https://curl.haxx.se/ @@ -33,6 +33,12 @@ Patch119: backport-CVE-2021-22945.patch Patch120: backport-0001-CVE-2021-22946.patch Patch121: backport-0002-CVE-2021-22946.patch Patch122: backport-CVE-2021-22947.patch +Patch123: backport-CVE-2022-22576.patch +Patch124: backport-CVE-2022-27775.patch +Patch125: backport-CVE-2022-27776.patch +Patch126: backport-pre-CVE-2022-27774.patch +Patch127: backport-001-CVE-2022-27774.patch +Patch128: backport-002-CVE-2022-27774.patch BuildRequires: automake brotli-devel coreutils gcc groff krb5-devel BuildRequires: libidn2-devel libnghttp2-devel libpsl-devel @@ -174,6 +180,12 @@ rm -rf ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_mandir}/man3/* %changelog +* Fri May 06 2022 gaihuiying - 7.71.1-13 +- Type:cves +- CVE:CVE-2022-22576 CVE-2022-27774 CVE-2022-27775 CVE-2022-27776 +- SUG:NA +- DESC:fix CVE-2022-22576 CVE-2022-27774 CVE-2022-27775 CVE-2022-27776 + * Thu Jan 20 2021 gaoxingwang - 7.71.1-12 - Type:CVE - CVE:CVE-2021-22922 CVE-2021-22923