HexBrain

curl · Report #4105790

FTP authentication options leak to a cross-origin FTP redirect with unrestricted auth disabled

N/Astatus
lowseverity
1upvotes
26 Oct 2026disclosed

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-2974 reads STRING_FTP_ACCOUNT after reply 332 and sends ACCT <value> without an origin check.
  • lib/ftp.c:2975-2994 reads STRING_FTP_ALTERNATIVE_TO_USER after failed USER/PASS authentication and sends it without an origin check.
  • lib/vauth/vauth.c:137-149 contains the existing initial-origin gate used for authentication, cookies, and other sensitive data.
  • lib/protocol.h:70-72 includes FTP and FTPS in the default redirect protocol set.

Steps to reproduce

  1. Build the official curl 8.22.0 release with HTTP and FTP support.

  2. 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)
    
  3. Run the attached loopback-only probe:

    python3 ftp_auth_sticky_reuse_probe.py ./ftp-auth-sticky-reuse-client
    
  4. 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.

  5. 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.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original