VAITP Dataset

← Back to the dataset

CVE-2025-61911

python-ldap: LDAP injection in escape_filter_chars via crafted list/dict.

  • CVSS 5.5
  • CWE-75
  • Input Validation and Sanitization
  • Remote

python-ldap is a lightweight directory access protocol (LDAP) client API for Python. In versions prior to 3.4.5, the sanitization method `ldap.filter.escape_filter_chars` can be tricked to skip escaping of special characters when a crafted `list` or `dict` is supplied as the `assertion_value` parameter, and the non-default `escape_mode=1` is configured. The method `ldap.filter.escape_filter_chars` supports 3 different escaping modes. `escape_mode=0` (default) and `escape_mode=2` happen to raise exceptions when a `list` or `dict` object is supplied as the `assertion_value` parameter. However, `escape_mode=1` computes without performing adequate logic to ensure a fully escaped return value. If an application relies on the vulnerable method in the `python-ldap` library to escape untrusted user input, an attacker might be able to abuse the vulnerability to launch ldap injection attacks which could potentially disclose or manipulate ldap data meant to be inaccessible to them. Version 3.4.5 fixes the issue by adding a type check at the start of the `ldap.filter.escape_filter_chars` method to raise an exception when the supplied `assertion_value` parameter is not of type `str`.

CVSS base score
5.5
Published
2025-10-10
OWASP
A03 Injection
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Input Validation and Sanitization
Subcategory
Command Injection
Accessibility scope
Remote
Impact
Unauthorized Access
Affected component
python-ldap
Fixed by upgrading
Yes

Solution

Upgrade `python-ldap` to version 3.4.5 or later.

Vulnerable code sample

import ldap.filter

# This code demonstrates the vulnerability in python-ldap versions prior to 3.4.5.
# A vulnerable version (e.g., 3.4.4) is required to run this code successfully.
# pip install python-ldap==3.4.4

# 1. Attacker-controlled input is provided as a list, which the vulnerable
#    function does not handle correctly. The payload is designed to inject
#    a wildcard search for any user.
malicious_payload = ["user1)(uid=*", ")"]

# 2. The application uses ldap.filter.escape_filter_chars with the non-default
#    `escape_mode=1`. In vulnerable versions, this mode processes a list
#    by simply concatenating its elements without escaping special characters.
unescaped_value = ldap.filter.escape_filter_chars(
    assertion_value=malicious_payload,
    escape_mode=1
)

# 3. The application constructs the final LDAP filter, assuming the user input
#    has been properly sanitized.
ldap_search_filter = f"(cn={unescaped_value})"

# 4. The resulting filter is malformed due to the lack of escaping.
#    Instead of searching for a user whose 'cn' is literally "user1)(uid=*)",
#    the injected filter becomes "(cn=user1)(uid=*)", which searches for a
#    user with 'cn' of 'user1' AND any user with a 'uid' attribute.
print(f"Intended Filter: (cn=user1\\29\\28uid\\3d*\\29)")
print(f"Injected Filter: {ldap_search_filter}")

Patched code sample

def escape_filter_chars(assertion_value, escape_mode=0):
    """
    A conceptual representation of the fixed ldap.filter.escape_filter_chars
    method as of version 3.4.5.
    """
    # FIX: A type check is added at the beginning of the method.
    # This check ensures that the function raises a TypeError if the input
    # is not a string, regardless of the escape_mode. This prevents crafted
    # list or dict objects from reaching the flawed logic path that previously
    # existed for escape_mode=1.
    if not isinstance(assertion_value, str):
        raise TypeError(
            "assertion_value must be a string, not %s" % type(assertion_value).__name__
        )

    # The original escaping logic follows. This part of the function is
    # now protected by the type check above. This is a simplified
    # representation for demonstration purposes.
    if escape_mode == 1:
        # Simplified representation of escaping logic for mode 1
        escaped_value = assertion_value.replace('\\', '\\5c')
        escaped_value = escaped_value.replace('*', '\\2a')
        escaped_value = escaped_value.replace('(', '\\28')
        escaped_value = escaped_value.replace(')', '\\29')
        escaped_value = escaped_value.replace('\x00', '\\00')
        return escaped_value
    else: # Default mode (0) or mode 2
        # Simplified representation of the default escaping logic
        escaped_value = assertion_value.replace('\\', '\\5c')
        escaped_value = escaped_value.replace(',', '\\2c')
        escaped_value = escaped_value.replace('*', '\\2a')
        escaped_value = escaped_value.replace('(', '\\28')
        escaped_value = escaped_value.replace(')', '\\29')
        escaped_value = escaped_value.replace('\x00', '\\00')
        return escaped_value

Payload

['*))(|(uid=*)']

Cite this entry

@misc{vaitp:cve202561911,
  title        = {{python-ldap: LDAP injection in escape_filter_chars via crafted list/dict.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2025},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2025-61911},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-61911/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::