Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Parasoft Jtest 2022.2

The Lightweight Directory Access Protocol (LDAP) allows an application to remotely perform operations such as searching and modifying records existing in directories. LDAP injection results from inadequate input sanitization and validation and allows malicious users to glean restricted information using the directory service.

A white-list whitelist can be used to restrict input to a list of valid characters. The list of characters Characters and character sequences that must not be allowed in a white-list include JNDI meta-characters and LDAP special characters. They are tabulated below:be excluded from whitelists—including Java Naming and Directory Interface (JNDI) metacharacters and LDAP special characters—are listed in the following table.

Characters and Sequences to Exclude from Whitelists

Character

Name

' and "

Single and double quote

/ and \

Forward

-

slash and

back-slash

backslash

\\

Double slashes*

space

Space character at beginning or end of string

#

Hash character at the beginning of the string

< and >

Angle brackets

, and ;

Comma and

semi-colon

semicolon

+ and *

Addition and multiplication operators

( and )

Round braces

\u0000

Unicode NULL character

* This is a character sequence.

...

LDAP Injection Example

For the purpose of this example, consider Consider an LDAP Data Interchange Format (LDIF) file that contains records in the following format:

Code Block

dn: dc=example,dc=com
objectclass: dcobject
objectClass: organization
o: Some Name
dc: example

dn: ou=People,dc=example,dc=com
ou: People
objectClass: dcobject
objectClass: organizationalUnit
dc: example

dn: cn=Manager,ou=People,dc=example,dc=com
cn: Manager
sn: John Watson
# Several objectClass definitions here (omitted)
userPassword: secret1
mail: john@holmesassociates.com

dn: cn=Senior Manager,ou=People,dc=example,dc=com
cn: Senior Manager
sn: Sherlock Holmes
# Several objectClass definitions here (omitted)
userPassword: secret2
mail: sherlock@holmesassociates.com

A search for a valid user name and password often takes the form

Code Block
(&(sn=<USERSN>)(userPassword=<USERPASSWORD>))

However, an attacker could bypass authentication by using S* for the USERSN field and * for the USERPASSWORD field. Such input would yield every record whose USERSN field began with S.

An authentication routine that permitted LDAP injection would allow unauthorized users to log in. Likewise, a search routine would allow an attacker to discover part or all of the data in the directory.

Noncompliant Code Example

This noncompliant code example allows a caller of the method searchRecord() to search for a record in the directory using the LDAP protocol. The string filter is responsible for filtering used to filter the result set on the basis of for those entries that match a user name and password that the caller must supply. If a malicious user enters specially crafted input, this elementary authentication scheme fails to confine the output of the search query to the information that the user is privileged to access. For example, the user may see any record beginning with "S" by supplying the values S* and * for the string variables userSN and UserPassword respectively. Consequently, information about any user can be gleaned without any prior knowledge of a particular user name and password pair. supplied by the caller.

Code Block
bgColor#FFCCCC

// String userSN = "S*"; // Invalid
// String userPassword = "*"; // Invalid
public class LDAPInjection {        
  private void searchRecord(String userSN, String userPassword) throws NamingException {         
    Hashtable<String, String>  env = new Hashtable<String, String>();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    try {
      DirContext dctx = new InitialDirContext(env);
		             
      SearchControls sc = new SearchControls();
      String[] attributeFilter = {"cn", "mail"};
      sc.setReturningAttributes(attributeFilter);
      sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
      String base = "dc=example,dc=com";
 
      // The following resolves to (&(sn=S*)(userPassword=*))      
      String filter = "(&(sn=" + userSN + ")(userPassword=" + userPassword + "))"; 
 
      NamingEnumeration<?> results = dctx.search(base, filter, sc);
      while (results.hasMore()) {
        SearchResult sr = (SearchResult) results.next();
        Attributes attrs = (Attributes) sr.getAttributes();
        Attribute attr = (Attribute) attrs.get("cn");
        System.out.println(attr.get());
        attr = (Attribute) attrs.get("mail");
        System.out.println(attr.get());
      }    
      dctx.close();
    } catch (NamingException e) {
      // Forward to Handlehandler
    }
  }  
}

When a malicious user enters specially crafted input, as outlined previously, this elementary authentication scheme fails to confine the output of the search query to the information for which the user has access privileges.

Compliant Solution

This compliant solution uses a white-list whitelist to validate sanitize user input so that the filter string contains only valid characters appear in the filter string. For example. In this code, userSN may contain only letters and spaces, whereas a password may contain only alphanumeric characters.

Code Block
bgColor#ccccff

// String userSN = "Sherlock Holmes"; // Valid
// String userPassword = "secret2";   // Valid

// ... beginning of LDAPInjection.searchRecord()...
sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
String base = "dc=example,dc=com";
           
if (!userSN.matches("[\\w\\s]*") || !userPassword.matches("[\\w]*")) {
  throw new IllegalArgumentException("Invalid input");
} 
            	
String filter = "(&(sn = " + userSN + ")(userPassword=" + userPassword + "))";
 
// ... remainder of LDAPInjection.searchRecord()...     

If it is desired to include special characters in When a database field such as a password must include special characters, it is critical to ensure that the authentic data is stored in a sanitized form in the database and also that any user input is escaped and transformed into the equivalent form, normalized before the validation or comparison takes place. The use of Using characters that have special meanings in JNDI and LDAP is strongly discouraged unless in the absence of a comprehensive whitenormalization and whitelisting-listing based routine is employed to encode and escape the characters. Refer to the guideline IDS04-J. Properly encode or escape output for examples on output encoding and escaping. The special character discouraged. Special characters must be transformed to a sanitized, safe value before adding it values before they are added to the white-list whitelist expression against which input is required to will be validated. Likewise, sanitization normalization of user input (escaping and encoding) should occur before the validation step.

...

Applicability

Failing Failure to sanitize untrusted input can result in information disclosure and privilege escalation.

...

Automated Detection

Severity
Tool
Likelihood
Version
Remediation Cost
Checker
Priority
Description

Level

IDS11- J

high

likely

medium

P18

L1

Automated Detection

TODO

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

Wiki Markup
\[[API 2006|AA. Java References#API 06]\] 
\[[OWASP 2008|AA. Java References#OWASP 08]\] [Preventing LDAP Injection in Java|http://www.owasp.org/index.php/Preventing_LDAP_Injection_in_Java]

The Checker Framework

Include Page
The Checker Framework_V
The Checker Framework_V

Tainting CheckerTrust and security errors (see Chapter 8)
Parasoft Jtest
Include Page
Parasoft_V
Parasoft_V
CERT.IDS54.TDLDAPProtect against LDAP injection
SonarQube
Include Page
SonarQube_V
SonarQube_V
S2078

Bibliography


...

Image Added Image Added Image AddedIDS10-J. Prevent XML external entity attacks      10. Input Validation and Data Sanitization (IDS)      IDS12-J. Prevent code injection