1From 620ea21410030a9977396b4661806bc187231b79 Mon Sep 17 00:00:00 2001 2From: Daniel Stenberg <daniel@haxx.se> 3Date: Mon, 25 Apr 2022 16:24:33 +0200 4Subject: [PATCH] transfer: redirects to other protocols or ports clear auth 5 6... unless explicitly permitted. 7 8Bug: https://curl.se/docs/CVE-2022-27774.html 9Reported-by: Harry Sintonen 10Closes #8748 11--- 12 lib/transfer.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 13 1 file changed, 48 insertions(+), 1 deletion(-) 14 15diff --git a/lib/transfer.c b/lib/transfer.c 16index 53ef0b03b8e0..315da876c4a8 100644 17--- a/lib/transfer.c 18+++ b/lib/transfer.c 19@@ -1611,10 +1611,57 @@ CURLcode Curl_follow(struct Curl_easy *data, 20 return CURLE_OUT_OF_MEMORY; 21 } 22 else { 23- 24 uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0); 25 if(uc) 26 return Curl_uc_to_curlcode(uc); 27+ 28+ /* Clear auth if this redirects to a different port number or protocol, 29+ unless permitted */ 30+ if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) { 31+ char *portnum; 32+ int port; 33+ bool clear = FALSE; 34+ 35+ if(data->set.use_port && data->state.allow_port) 36+ /* a custom port is used */ 37+ port = (int)data->set.use_port; 38+ else { 39+ uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum, 40+ CURLU_DEFAULT_PORT); 41+ if(uc) { 42+ free(newurl); 43+ return Curl_uc_to_curlcode(uc); 44+ } 45+ port = atoi(portnum); 46+ free(portnum); 47+ } 48+ if(port != data->info.conn_remote_port) { 49+ infof(data, "Clear auth, redirects to port from %u to %u", 50+ data->info.conn_remote_port, port); 51+ clear = TRUE; 52+ } 53+ else { 54+ char *scheme; 55+ const struct Curl_handler *p; 56+ uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0); 57+ if(uc) { 58+ free(newurl); 59+ return Curl_uc_to_curlcode(uc); 60+ } 61+ 62+ p = Curl_builtin_scheme(scheme); 63+ if(p && (p->protocol != data->info.conn_protocol)) { 64+ infof(data, "Clear auth, redirects scheme from %s to %s", 65+ data->info.conn_scheme, scheme); 66+ clear = TRUE; 67+ } 68+ free(scheme); 69+ } 70+ if(clear) { 71+ Curl_safefree(data->state.aptr.user); 72+ Curl_safefree(data->state.aptr.passwd); 73+ } 74+ } 75 } 76 77 if(type == FOLLOW_FAKE) { 78