Skip to main content

Avoid LDAP Injection Attacks

Critical
securityinjections

What is it?

LDAP injections occur when untrusted data is inserted into an LDAP query without proper sanitization or validation, potentially allowing execution of malicious LDAP commands.

Why apply it?

This vulnerability can lead to data leakage, corruption, or privilege escalation. LDAP servers are often critical to organizational infrastructure, making them a target for attackers.

How to fix it?

Use parameterized queries to safely include user input in LDAP queries. Alternatively, sanitize inputs using libraries like OWASP's ESAPI, using functions such as encodeForLDAP.

Examples

Example 1:

Negative

The negative example directly concatenates user inputs into the LDAP query, exposing it to injection risks.

import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.servlet.http.HttpServletRequest;
import javax.naming.NamingEnumeration;
import javax.naming.directory.SearchResult;

public class LdapAuthenticator {
public boolean authenticate(HttpServletRequest req, DirContext ctx) throws NamingException {
String user = req.getParameter("user");
String pass = req.getParameter("pass");

String filter = "(&(uid=" + user + ")(userPassword=" + pass + "))";

NamingEnumeration<SearchResult> results = ctx.search(
"ou=system",
filter,
new SearchControls()
);

return results.hasMore();
}
}

Example 2:

Positive

The positive example uses a parameterized query to safely include user input, preventing injection attacks.

import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.servlet.http.HttpServletRequest;
import javax.naming.NamingEnumeration;
import javax.naming.directory.SearchResult;

public class LdapAuthenticator {
public boolean authenticate(HttpServletRequest req, DirContext ctx) throws NamingException {
String user = req.getParameter("user");
String pass = req.getParameter("pass");

String filter = "(&(uid={0})(userPassword={1}))";

NamingEnumeration<SearchResult> results = ctx.search(
"ou=system",
filter,
new String[]{user, pass},
new SearchControls()
);

return results.hasMore();
}
}

Negative

The negative example directly uses user input in the LDAP query without any sanitization or encoding.

import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.servlet.http.HttpServletRequest;
import javax.naming.NamingEnumeration;
import javax.naming.directory.SearchResult;

public class UnsafeLdapSearch {
public boolean searchUser(HttpServletRequest req, DirContext ctx) throws NamingException {
String user = req.getParameter("user");
String pass = req.getParameter("pass");

String filter = "(&(uid=" + user + ")(userPassword=" + pass + "))";

NamingEnumeration<SearchResult> results = ctx.search(
"ou=users",
filter,
new SearchControls()
);

return results.hasMore();
}
}

Example 3:

Positive

The positive example sanitizes user input using an encoding function to neutralize special characters.

import org.owasp.esapi.ESAPI;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.servlet.http.HttpServletRequest;
import javax.naming.NamingEnumeration;
import javax.naming.directory.SearchResult;

public class SafeLdapSearch {
public boolean searchUser(HttpServletRequest req, DirContext ctx) throws NamingException {
String user = ESAPI.encoder().encodeForLDAP(req.getParameter("user"));
String pass = ESAPI.encoder().encodeForLDAP(req.getParameter("pass"));

String filter = "(&(uid=" + user + ")(userPassword=" + pass + "))";

NamingEnumeration<SearchResult> results = ctx.search(
"ou=users",
filter,
new SearchControls()
);

return results.hasMore();
}
}