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