LDAP Injection

ID

python.ldap_injection

Severity

critical

Resource

Injection

Language

Python

Tags

CWE:90, NIST.SP.800-53, OWASP:2021:A3, PCI-DSS:6.5.1

Description

LDAP Injection in Python applications occurs when untrusted input is used to construct LDAP queries without proper sanitization, allowing attackers to manipulate the query and access or modify sensitive directory data.

Rationale

LDAP Injection vulnerabilities allow attackers to modify LDAP queries by injecting malicious input into them. In Python, this typically occurs when using libraries such as ldap3 or python-ldap to construct search filters directly from user-supplied data.

Consider the following vulnerable code snippet:

from ldap3 import Server, Connection, ALL

server = Server('ldap://example.com', get_info=ALL)
conn = Connection(server, 'cn=admin,dc=example,dc=com', 'password', auto_bind=True)

username = input("Enter your username: ")
search_filter = f"(uid={username})"
conn.search('dc=example,dc=com', search_filter, attributes=['cn', 'mail'])

If a user inputs something like )(|(uid=)), the constructed query becomes: (uid=)(|(uid=))

This broadens the search to return all users, effectively bypassing the intended access control.

The danger is amplified when such queries are used for authentication or authorization checks, leading to privilege escalation or unauthorized access.

Remediation

To mitigate LDAP Injection in Python, follow these best practices:

  1. Avoid direct string formatting when building LDAP filters. Use safe query construction functions when available.

  2. Escape special characters in user input. Python’s ldap.filter.escape_filter_chars() (in python-ldap) can be used for this purpose.

Here’s the secure version of the earlier example:

import ldap.filter
from ldap3 import Server, Connection, ALL

server = Server('ldap://example.com', get_info=ALL)
conn = Connection(server, 'cn=admin,dc=example,dc=com', 'password', auto_bind=True)

username = input("Enter your username: ")
safe_username = ldap.filter.escape_filter_chars(username)
search_filter = f"(uid={safe_username})"
conn.search('dc=example,dc=com', search_filter, attributes=['cn', 'mail'])

This escapes characters such as *, (, ), and |, preventing injection.

Additional recommendations: - Validate and constrain input using whitelisting approaches where possible. - Use least privilege principles to limit LDAP account access. - Log and monitor LDAP queries for anomalies.

Always review your SAST tool’s rule set for LDAP Injection to ensure it flags dynamic LDAP filter construction and recommends appropriate escaping and validation mechanisms.

Configuration

The detector has the following configurable parameters:

  • sources, that indicates the source kinds to check.

  • neutralizations, that indicates the neutralization kinds to check.