curl · Report #4105790
FTP authentication options leak to a cross-origin FTP redirect with unrestricted auth disabled
How it was found
Summary
libcurl 8.22.0 sends values configured with CURLOPT_FTP_ACCOUNT and CURLOPT_FTP_ALTERNATIVE_TO_USER to a different origin reached through an HTTP-to-FTP redirect even when unrestricted authentication is disabled. I reproduced this after a successful legitimate FTP download by reusing the same easy handle, which matches libcurl's documented handle-reuse and sticky-option behavior. The later HTTP response redirects from http://localhost:<port> to an attacker-controlled ftp://127.0.0.1:<other-port>, changing hostname, scheme, and port. Although CURLOPT_UNRESTRICTED_AUTH is explicitly 0L, the new FTP origin receives the retained account value or alternative authentication command. Disabling redirect following or clearing the affected option before the HTTP transfer prevents disclosure. This affects libcurl applications; the curl command-line tool does not set these FTP-only options for this initial-HTTP flow.
Affected version
Official curl/libcurl 8.22.0 release source, built locally on macOS with AddressSanitizer and UndefinedBehaviorSanitizer. The main test build reported:
libcurl/8.22.0 OpenSSL/3.6.3 zlib/1.2.12 libidn2/2.3.8 nghttp2/1.68.1 OpenLDAP/2.4.28/Apple
The full result also reproduced on a separately configured 8.22.0 build with libpsl 0.21.5.
Source location
lib/ftp.c:2957-2974readsSTRING_FTP_ACCOUNTafter reply 332 and sendsACCT <value>without an origin check.lib/ftp.c:2975-2994readsSTRING_FTP_ALTERNATIVE_TO_USERafter failed USER/PASS authentication and sends it without an origin check.lib/vauth/vauth.c:137-149contains the existing initial-origin gate used for authentication, cookies, and other sensitive data.lib/protocol.h:70-72includes FTP and FTPS in the default redirect protocol set.
Steps to reproduce
-
Build the official curl 8.22.0 release with HTTP and FTP support.
-
Compile the attached client against that build, for example:
cc -o ftp-auth-sticky-reuse-client ftp_auth_sticky_reuse_client.c $(/path/to/curl-8.22.0/bin/curl-config --cflags --libs) -
Run the attached loopback-only probe:
python3 ftp_auth_sticky_reuse_probe.py ./ftp-auth-sticky-reuse-client -
The probe first completes an authenticated FTP download, then reuses the same handle for HTTP and compares redirect-following, no-follow, and explicit-option-clear cases for both affected options.
-
The expected summaries are:
summary mode=account sticky_first_success=1 sticky_redirect_auth=1 nofollow_redirect_auth=0 cleared_redirect_auth=0 expected=1 summary mode=alternative sticky_first_success=1 sticky_redirect_auth=1 nofollow_redirect_auth=0 cleared_redirect_auth=0 expected=1
The first FTP transfer returns CURLE_OK in every case. In the sticky-follow cases the redirected FTP peer receives ACCT <SYNTHETIC_ACCOUNT_MARKER> or <SYNTHETIC_ALTERNATIVE_AUTH_COMMAND>; the controls do not disclose either value. All traffic is loopback-only and all authentication-like values are synthetic.
Expected result
FTP authentication values retained on a reused handle should not be sent after a redirect changes hostname, scheme, and port unless the caller explicitly enables unrestricted authentication.
AI-use disclosure
AI assistance was used for source analysis and local test generation. I checked the claims against the curl 8.22.0 production source, reproduced both option paths on two independent sanitizer-enabled builds, and reviewed public curl issues and advisories for duplicates.
Impact
An attacker who controls an HTTP response consumed by an affected libcurl application can redirect a reused easy handle to an attacker-operated FTP server and obtain FTP authentication material retained from an earlier legitimate FTP transfer. The attacker does not need access to the legitimate FTP server or to complete authentication at the redirected server. Depending on the application, the disclosed value can be an account or tenant identifier, token, or server-specific authentication command. I rate this Low because exploitation requires one of two specialized FTP options, cross-protocol handle reuse without clearing it, an attacker-influenced HTTP response, and a followed FTP redirect.