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.escapeValueescapes 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 asauth-conf.