HexBrain

curl · Report #3822248

CVE-2026-13608: OpenLDAP SASL authentication bypass

Validstatus
lowseverity
6upvotes
3 Sept 2026disclosed

How it was found

Summary:

In lib/openldap.c, oldap_state_sasl_resp() transitions to OLDAP_STOP (connection ready) whenever Curl_sasl_continue() returns CURLE_OK with progress != SASL_INPROGRESS. This condition does not distinguish SASL_DONE (authentication completed) from SASL_IDLE (no mechanism available). A malicious LDAP server can send a malformed SASL challenge, causing the client to cancel the mechanism and retry with no remaining mechanisms. Curl_sasl_start() then returns CURLE_OK with progress == SASL_IDLE, and the connection proceeds as if authentication succeeded. This bypasses Kerberos (GSSAPI) mutual authentication: an attacker without a valid keytab can impersonate a server and inject arbitrary LDAP responses.

Affected version

curl 8.21.0-DEV (Linux) libcurl/8.21.0-DEV OpenSSL/3.0.13 zlib/1.3 mit-krb5/1.20.1 OpenLDAP/2.6.10
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps pop3 pop3s rtsp smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS GSS-API HSTS HTTPS-proxy IPv6 Kerberos Largefile libz SPNEGO SSL threadsafe TLS-SRP UnixSockets

Tested on Ubuntu 24.04 (x86_64) against commit 68720b4837284335b2d63cb358f8f6ce65f5bc55 (HEAD of master as of 2026-06-24). The vulnerable code has been present since the OpenLDAP SASL support was introduced and is unchanged in the current release.

Platform: Linux 6.8.0, x86_64, MIT Kerberos 1.20.1, OpenLDAP 2.6.10.

Steps To Reproduce:

Prerequisites

  1. curl/libcurl built with OpenLDAP backend (-DUSE_OPENLDAP=ON) and GSSAPI (-DCURL_USE_GSSAPI=ON)
  2. A working Kerberos environment (KDC with realm, kinit to obtain a TGT)
  3. Python 3 (for the mock server)

Setup

# Build curl with OpenLDAP + GSSAPI
cmake -B build -DCURL_DISABLE_LDAP=OFF -DUSE_OPENLDAP=ON \
  -DCURL_USE_GSSAPI=ON -DCURL_USE_OPENSSL=ON -DCURL_USE_LIBPSL=OFF \
  -DCURL_USE_LIBIDN2=OFF -DCMAKE_BUILD_TYPE=Debug
cmake --build build -j$(nproc)

# Set up minimal KDC (example for MIT Kerberos)
sudo kdb5_util create -s -P testpass123          # realm: TEST.LOCAL
sudo kadmin.local -q "addprinc -pw testpass [email protected]"
sudo kadmin.local -q "addprinc -randkey ldap/[email protected]"
sudo kadmin.local -q "ktadd -k /tmp/ldap.keytab ldap/[email protected]"
sudo krb5kdc

# Obtain TGT
echo testpass | kinit [email protected]

Mock LDAP server (attacker — has NO keytab)

Run the attached mock_gssapi_server.py:

python3 mock_gssapi_server.py 3893

The server triggers SASL_CANCEL as follows:

  1. Advertises only GSSAPI in supportedSASLMechanisms.
  2. Receives the client's SASL BindRequest containing a Kerberos AP-REQ (which it cannot decrypt).
  3. Replies with LDAP_SASL_BIND_IN_PROGRESS (resultCode 14) and a garbage serverSaslCreds value (\x60\x10\xDE\xAD...). This invalid GSSAPI token causes gss_init_sec_context() to fail, which libcurl translates to CURLE_BAD_CONTENT_ENCODING — the condition that enters the SASL_CANCEL state.
  4. Acknowledges the subsequent cancel BindRequest with LDAP_SUCCESS (resultCode 0).

Trigger the bug

# Ensure valid TGT exists
klist

# Connect to malicious server with GSSAPI auth
./build/src/curl --user "[email protected]:testpass" \
    --login-options "AUTH=GSSAPI" \
    "ldap://localhost:3893/dc=example,dc=com?*?sub" \
    --connect-timeout 5 --max-time 10

Expected result (fixed behavior)

curl should report authentication failure (exit code 67, CURLE_LOGIN_DENIED).

Actual result

DN: cn=admin,dc=example,dc=com
	cn: admin
	uid: attacker-injected
	userPassword: {CLEAR}pwned
	sshPublicKey: ssh-ed25519 AAAA_ATTACKER_KEY attacker@evil
	description: INJECTED via CWE-306 Kerberos bypass

Exit code: 0

curl considers the connection authenticated and proceeds to execute the LDAP query. The attacker's injected data is returned to the client as trusted LDAP results.

Root Cause

In lib/openldap.c line 786:

result = Curl_sasl_continue(&li->sasl, data, code, &progress);
if(!result && progress != SASL_INPROGRESS)   // ← does not distinguish SASL_DONE from SASL_IDLE
    oldap_state(data, li, OLDAP_STOP);

https://github.com/curl/curl/blob/68720b4837284335b2d63cb358f8f6ce65f5bc55/lib/openldap.c#L786-L787

When Curl_sasl_continue() enters the SASL_CANCEL case (lib/curl_sasl.c line 773-780), it removes the failed mechanism and calls Curl_sasl_start(). If no mechanisms remain, Curl_sasl_start() returns CURLE_OK with *progress = SASL_IDLE (line 519):

https://github.com/curl/curl/blob/68720b4837284335b2d63cb358f8f6ce65f5bc55/lib/curl_sasl.c#L519 https://github.com/curl/curl/blob/68720b4837284335b2d63cb358f8f6ce65f5bc55/lib/curl_sasl.c#L773-L780

Suggested fix

result = Curl_sasl_continue(&li->sasl, data, code, &progress);
if(!result && progress == SASL_DONE)          // ← only accept explicit completion
    oldap_state(data, li, OLDAP_STOP);
else if(!result && progress == SASL_IDLE)
    result = CURLE_LOGIN_DENIED;

Impact

Summary:

A malicious LDAP server (or network attacker in MITM position) can bypass SASL authentication in libcurl's OpenLDAP backend by sending a single malformed SASL challenge. The most significant impact is against GSSAPI (Kerberos), where the bypass nullifies mutual authentication: the client proceeds without verifying the server holds a valid keytab. This allows the attacker to:

  1. Capture client queries — leaking the LDAP search base DN, filter, and requested attributes.
  2. Inject arbitrary LDAP results — the client accepts fabricated directory entries (e.g., forged SSH public keys, group memberships, or credentials) as trusted data.

Prerequisites:

  1. libcurl built with the OpenLDAP backend (USE_OPENLDAP) and Kerberos support.
  2. The application must configure SASL authentication (e.g., CURLOPT_LOGIN_OPTIONS "AUTH=GSSAPI").
  3. The attacker must be positioned as MITM or control the target LDAP server's address (DNS poisoning, ARP spoofing, etc.).
  4. The connection must not use LDAPS/TLS (or the client must not properly validate the server certificate), since TLS would independently block MITM.

The impact is highest in environments that rely on Kerberos for server identity verification on non-TLS LDAP connections.

The initial discovery was made by AI. All technical claims have been reviewed and revised by human experts.

Reporting on behalf of Autonomous Code Security (ACS) team at Microsoft.

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