| From 50aebd6ea20956513e9b7d7c776830b54d9c8ff6 Mon Sep 17 00:00:00 2001 |
| From: Daniel Stenberg <daniel@haxx.se> |
| Date: Mon, 25 Apr 2022 16:24:33 +0200 |
| Subject: [PATCH] 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 |
| Closes #8748 |
| |
| Upstream-Status: Backport [https://github.com/curl/curl/commit/620ea21410030a9977396b4661806bc187231b79] |
| Signed-off-by: Robert Joslyn <robert.joslyn@redrectangle.org> |
| --- |
| lib/transfer.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- |
| 1 file changed, 48 insertions(+), 1 deletion(-) |
| |
| diff --git a/lib/transfer.c b/lib/transfer.c |
| index 1f8019b..752fe14 100644 |
| --- a/lib/transfer.c |
| +++ b/lib/transfer.c |
| @@ -1608,10 +1608,57 @@ 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; |
| + |
| + if(data->set.use_port && data->state.allow_port) |
| + /* a custom port is used */ |
| + port = (int)data->set.use_port; |
| + else { |
| + 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->state.aptr.user); |
| + Curl_safefree(data->state.aptr.passwd); |
| + } |
| + } |
| } |
| |
| if(type == FOLLOW_FAKE) { |