﻿# V5321\. OWASP\. Possible LDAP injection\. Potentially tainted data is used in a search filter\.

The analyzer has detected that potentially tainted data is used to construct an LDAP query filter\. If data is not properly sanitized, this can lead to LDAP injection, a vulnerability similar to SQL injection\.

This vulnerability can be categorized under the OWASP Top 10 2021 classification as follows:

* [A3:2021\-Injection\.](https://owasp.org/Top10/A03_2021-Injection/)

The example:

```cpp
public void search(HttpServletRequest request) throws NamingException {
  String user = request.getParameter("user");
  String password = request.getParameter("password");
  String searchFilter = "(&(uid=" + user + ")(userPassword=" + password + "))";
  DirContext context = new InitialDirContext(getEnv());

  var result = context.search("ou=users,dc=example,dc=com", 
    searchFilter, null); // <=
  if (result.hasMore()) {
    ....
  }
}
```

In the example, a search filter is constructed to provide some sensitive information to a user with a certain username and password\. The filter uses the values of the `user` and `password` variables obtained from an external source\. Using data in this manner is dangerous, as attackers can manipulate the search filter\.

Here are a few examples to illustrate the attack\.

If `user` contains `PVS` and `password` contains `Studio`, developers will get the following query:

```cpp
LDAP query: (&(uid=PVS)(userPassword=Studio))
```

In this case, developers receive the expected data from the user\. If a username and password combination are valid, access will be granted\.

Consider that the following values being written in the 'user' and 'password' variables:

```cpp
user: PVS)(uid=PVS))(|(uid=PVS)
password: Any
```

When these values are inserted into the LDAP query template, the resulting filter is:

```cpp
LDAP query: (&(uid=PVS)(uid=PVS))(|(uid=PVS)(userPassword=Any))
```

Using such a search filter can grant access, even if attackers enter an incorrect password\. This happens because LDAP will only process the first filter, and `(|(uid=PVS)(userPassword=Any))` will be ignored\.

To harden security, it is important to validate all input data or escape all special characters in the user\-supplied data\.

Here is the code example that uses the escape method to handle user\-supplied data:

```cpp
private static String escapeLdapInput(String input) {
  return input.replace("(", "\\28").replace(")", "\\29")
              .replace("*", "\\2a").replace("|", "\\7c")
              .replace("&", "\\26").replace("!", "\\21")
              .replace("=", "\\3d").replace(">", "\\3e")
              .replace("<", "\\3c").replace("\\", "\\5c");
}

public void safeSearch(HttpServletRequest request) throws NamingException {
  String user = request.getParameter("user");
  String password = request.getParameter("password");
  String escapedUser = escapeLdapInput(user);
  String escapedPassword = escapeLdapInput(password);
  String searchFilter = "(&(uid=" + escapedUser + 
                        ")(userPassword=" + escapedPassword + "))";

  DirContext context = new InitialDirContext(getEnv());
  var result = context.search("ou=users,dc=example,dc=com",
    searchFilter, null); 
  if (result.hasMore()) {
    ....
  }
}
```