1From 50aebd6ea20956513e9b7d7c776830b54d9c8ff6 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 12Upstream-Status: Backport [https://github.com/curl/curl/commit/620ea21410030a9977396b4661806bc187231b79] 13Signed-off-by: Robert Joslyn <robert.joslyn@redrectangle.org> 14--- 15 lib/transfer.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 16 1 file changed, 48 insertions(+), 1 deletion(-) 17 18diff --git a/lib/transfer.c b/lib/transfer.c 19index 1f8019b..752fe14 100644 20--- a/lib/transfer.c 21+++ b/lib/transfer.c 22@@ -1608,10 +1608,57 @@ CURLcode Curl_follow(struct Curl_easy *data, 23 return CURLE_OUT_OF_MEMORY; 24 } 25 else { 26- 27 uc = curl_url_get(data->state.uh, CURLUPART_URL, &newurl, 0); 28 if(uc) 29 return Curl_uc_to_curlcode(uc); 30+ 31+ /* Clear auth if this redirects to a different port number or protocol, 32+ unless permitted */ 33+ if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) { 34+ char *portnum; 35+ int port; 36+ bool clear = FALSE; 37+ 38+ if(data->set.use_port && data->state.allow_port) 39+ /* a custom port is used */ 40+ port = (int)data->set.use_port; 41+ else { 42+ uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum, 43+ CURLU_DEFAULT_PORT); 44+ if(uc) { 45+ free(newurl); 46+ return Curl_uc_to_curlcode(uc); 47+ } 48+ port = atoi(portnum); 49+ free(portnum); 50+ } 51+ if(port != data->info.conn_remote_port) { 52+ infof(data, "Clear auth, redirects to port from %u to %u", 53+ data->info.conn_remote_port, port); 54+ clear = TRUE; 55+ } 56+ else { 57+ char *scheme; 58+ const struct Curl_handler *p; 59+ uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0); 60+ if(uc) { 61+ free(newurl); 62+ return Curl_uc_to_curlcode(uc); 63+ } 64+ 65+ p = Curl_builtin_scheme(scheme); 66+ if(p && (p->protocol != data->info.conn_protocol)) { 67+ infof(data, "Clear auth, redirects scheme from %s to %s", 68+ data->info.conn_scheme, scheme); 69+ clear = TRUE; 70+ } 71+ free(scheme); 72+ } 73+ if(clear) { 74+ Curl_safefree(data->state.aptr.user); 75+ Curl_safefree(data->state.aptr.passwd); 76+ } 77+ } 78 } 79 80 if(type == FOLLOW_FAKE) { 81