java.lang.security.audit.ldap-injection.ldap-injection
Community Favorite
semgrep
Author
73,396
Download Count*
License
Detected non-constant data passed into an LDAP query. If this data can be controlled by an external user, this is an LDAP injection. Ensure data passed to an LDAP query is not controllable; or properly sanitize the data.
Run Locally
Run in CI
Defintion
rules:
- id: ldap-injection
message: Detected non-constant data passed into an LDAP query. If this data can
be controlled by an external user, this is an LDAP injection. Ensure data
passed to an LDAP query is not controllable; or properly sanitize the
data.
metadata:
cwe:
- "CWE-90: Improper Neutralization of Special Elements used in an LDAP
Query ('LDAP Injection')"
owasp:
- A01:2017 - Injection
- A03:2021 - Injection
source-rule-url: https://find-sec-bugs.github.io/bugs.htm#LDAP_INJECTION
asvs:
section: "V5: Validation, Sanitization and Encoding Verification Requirements"
control_id: 5.3.7 Injection
control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v53-output-encoding-and-injection-prevention-requirements
version: "4"
category: security
technology:
- java
references:
- https://owasp.org/Top10/A03_2021-Injection
subcategory:
- audit
likelihood: LOW
impact: HIGH
confidence: LOW
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- LDAP Injection
severity: WARNING
languages:
- java
patterns:
- pattern-either:
- pattern-inside: |
$X $METHOD(...) {
...
InitialDirContext $CTX = ...;
...
}
- pattern-inside: |
$X $METHOD(...) {
...
DirContext $CTX = ...;
...
}
- pattern-inside: |
$X $METHOD(...) {
...
InitialLdapContext $CTX = ...;
...
}
- pattern-inside: |
$X $METHOD(...) {
...
LdapContext $CTX = ...;
...
}
- pattern-inside: |
$X $METHOD(...) {
...
LdapCtx $CTX = ...;
...
}
- pattern-inside: |
$X $METHOD(...) {
...
EventDirContext $CTX = ...;
...
}
- pattern: |
$X $METHOD(...) {
...
$CTX.search($Y,$INPUT,...);
...
}
- pattern-not: |
$X $METHOD(...) {
...
$CTX.search($Y,"...",...);
...
}
Examples
ldap-injection.java
package testcode.ldap;
import com.sun.jndi.ldap.LdapCtx;
import javax.naming.Context;
import javax.naming.InvalidNameException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.event.EventDirContext;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.LdapName;
import java.util.Properties;
public class JndiLdapAdditionalSignature {
// ruleid: ldap-injection
public static void moreLdapInjections(String input) throws NamingException {
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
props.put(Context.PROVIDER_URL, "ldap://ldap.example.com");
props.put(Context.REFERRAL, "ignore");
SearchControls ctrls = new SearchControls();
ctrls.setReturningAttributes(new String[]{"givenName", "sn"});
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
DirContext context1 = new InitialDirContext(props);
NamingEnumeration<SearchResult> answers;
answers = context1.search(new LdapName("dc=People,dc=example,dc=com"), "(uid=" + input + ")", ctrls);
}
// ruleid: ldap-injection
public static void moreLdapInjections1(String input) throws NamingException {
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
props.put(Context.PROVIDER_URL, "ldap://ldap.example.com");
props.put(Context.REFERRAL, "ignore");
SearchControls ctrls = new SearchControls();
ctrls.setReturningAttributes(new String[]{"givenName", "sn"});
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
InitialDirContext context2 = new InitialDirContext(props);
NamingEnumeration<SearchResult> answers;
answers = context2.search(new LdapName("dc=People,dc=example,dc=com"), "(uid=" + input + ")", new Object[0], ctrls);
}
// ruleid: ldap-injection
public static void moreLdapInjections2(String input) throws NamingException {
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
props.put(Context.PROVIDER_URL, "ldap://ldap.example.com");
props.put(Context.REFERRAL, "ignore");
SearchControls ctrls = new SearchControls();
ctrls.setReturningAttributes(new String[]{"givenName", "sn"});
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
InitialLdapContext context3 = new InitialLdapContext();
LdapContext context4 = new InitialLdapContext();
NamingEnumeration<SearchResult> answers;
answers = context3.search("dc=People,dc=example,dc=com", "(uid=" + input + ")", ctrls);
}
// ruleid: ldap-injection
public static void moreLdapInjections3(String input) throws NamingException {
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
props.put(Context.PROVIDER_URL, "ldap://ldap.example.com");
props.put(Context.REFERRAL, "ignore");
SearchControls ctrls = new SearchControls();
ctrls.setReturningAttributes(new String[]{"givenName", "sn"});
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
LdapContext context4 = new InitialLdapContext();
NamingEnumeration<SearchResult> answers;
answers = context4.search("dc=People,dc=example,dc=com", "(uid=" + input + ")", new Object[0], ctrls);
}
// ruleid: ldap-injection
public void ldapInjectionSunApi5(String input) throws NamingException {
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
props.put(Context.PROVIDER_URL, "ldap://ldap.example.com");
props.put(Context.REFERRAL, "ignore");
SearchControls ctrls = new SearchControls();
ctrls.setReturningAttributes(new String[]{"givenName", "sn"});
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
LdapCtx context5 = new InitialDirContext(props);
NamingEnumeration<SearchResult> answers;
answers = context5.search("dc=People,dc=example,dc=com", "(uid=" + input + ")", new Object[0], ctrls);
}
// ruleid: ldap-injection
public void ldapInjectionSunApi6(String input) throws NamingException {
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
props.put(Context.PROVIDER_URL, "ldap://ldap.example.com");
props.put(Context.REFERRAL, "ignore");
SearchControls ctrls = new SearchControls();
ctrls.setReturningAttributes(new String[]{"givenName", "sn"});
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
EventDirContext context6 = new InitialDirContext(props);
NamingEnumeration<SearchResult> answers;
answers = context6.search("dc=People,dc=example,dc=com", "(uid=" + input + ")", new Object[0], ctrls);
}
// ok: ldap-injection
public static void moreLdapInjections4(String input) throws NamingException {
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
props.put(Context.PROVIDER_URL, "ldap://ldap.example.com");
props.put(Context.REFERRAL, "ignore");
SearchControls ctrls = new SearchControls();
ctrls.setReturningAttributes(new String[]{"givenName", "sn"});
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
DirContext context1 = new InitialDirContext(props);
NamingEnumeration<SearchResult> answers;
//False positive
answers = context1.search(new LdapName("dc=People,dc=example,dc=com"), "(uid=bob)", new Object[0], ctrls);
}
}
Short Link: https://sg.run/nd2O