Insecure LDAP Authentication (Cleartext Transmission)

LDAP simple bind over cleartext

Description

LDAP simple authentication sends the username and password in cleartext unless TLS or appropriate SASL protection secures the connection. A ldap:// connection can also be protected by applying StartTLS before binding. An attacker able to intercept traffic may steal these credentials through sniffing or a man-in-the-middle attack, then use them to take over accounts, escalate privileges, or access other internal systems.

Potential impact

  • Credential theft: Network interception can expose cleartext usernames and passwords.
  • Unauthorized access and privilege escalation: Stolen accounts may provide access to AD/LDAP resources and additional privileges.
  • Lateral movement: Reused credentials may give access to other internal systems.
  • Security policy violations: Cleartext passwords may breach an organization's encrypted-transmission requirements.
  • Credential reuse attacks: Captured simple-bind credentials can be used for repeated logins.

Remediation

  • Use ldaps:// to encrypt the connection with TLS, typically on port 636.
  • Apply StartTLS before authentication when the server supports upgrading a ldap:// connection.
  • Use SASL where appropriate: In a correctly configured Kerberos/JAAS environment, select GSSAPI and suitable quality of protection (QOP), such as auth-conf. Do not use the obsolete DIGEST-MD5 mechanism in new configurations.
  • Prohibit simple binds over connections without TLS or equivalent protection.
  • Configure a trusted certificate store and retain hostname verification to protect against interception.
  • Give service accounts only necessary privileges, rotate passwords as appropriate, and limit failed authentication attempts.

Examples

Before

java
import javax.naming.Context;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import java.util.Hashtable;

public class InsecureLdapLogin {
    public DirContext login(String user, String pass) throws Exception {
        Hashtable<String, String> env = new Hashtable<>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, "ldap://10.0.0.5:389"); // Cleartext connection
        env.put(Context.SECURITY_AUTHENTICATION, "simple");  // Simple Bind
        env.put(Context.SECURITY_PRINCIPAL, "uid=" + user + ",ou=people,dc=corp,dc=local");
        env.put(Context.SECURITY_CREDENTIALS, pass);
        return new InitialDirContext(env); // Credentials are sent in cleartext
    }
}

After

java
import javax.naming.Context;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.ldap.Rdn;
import java.util.Hashtable;

public class SecureLdapLogin {
    public DirContext login(String user, char[] pass) throws Exception {
        Hashtable<String, Object> env = new Hashtable<>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, "ldaps://ldap.corp.local:636"); // TLS-encrypted connection
        env.put(Context.SECURITY_AUTHENTICATION, "simple"); // Performed over TLS
        String userDn = "uid=" + Rdn.escapeValue(user)
                + ",ou=people,dc=corp,dc=local";
        env.put(Context.SECURITY_PRINCIPAL, userDn);
        env.put(Context.SECURITY_CREDENTIALS, new String(pass));
        // Use a JVM truststore containing approved CAs; keep endpoint identification enabled.
        return new InitialDirContext(env);
    }
}

// Alternative: SASL GSSAPI with a configured Kerberos/JAAS environment
// env.put(Context.PROVIDER_URL, "ldap://ldap.corp.local:389");
// env.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
// env.put("javax.security.sasl.qop", "auth-conf"); // Integrity and confidentiality protection

Explanation:

  • Before: The simple bind uses a ldap:// connection without TLS or equivalent protection, so the password travels in cleartext.
  • After: ldaps://, a trusted certificate store, and hostname verification protect the TLS connection. Rdn.escapeValue escapes the username as a DN attribute value. In a Kerberos environment, GSSAPI can be selected as the single authentication mechanism instead of obsolete DIGEST-MD5, with an explicit QOP such as auth-conf.

References