Bypassing corporate single sign-on with a few parentheses.
LDAP (Lightweight Directory Access Protocol) is heavily used in enterprise environments (like Microsoft Active Directory) to manage employee logins and network permissions. Applications often query LDAP using a specific syntax composed of parentheses and operators, like `(&(user=alice)(password=secret))`. This means "find an entry where the user is alice AND the password is secret".
If an application concatenates user input directly into an LDAP query filter, an attacker can inject structural characters like `)` and `*` to alter the logic, similar to SQL injection.
Unlike SQL, LDAP does not have a widespread concept of "Prepared Statements" (parameterization). Therefore, the only defense against LDAP Injection is strict input validation and properly escaping all special characters in the user's input before placing it in the query.
# VULNERABLE: Direct concatenation
username = request.form['username']
# DANGER: If username is "admin)(|(objectClass=*)"
# The query becomes: (&(uid=admin)(|(objectClass=*))(password=...))
ldap_filter = f"(&(uid={username})(password={password}))"
ldap_conn.search(search_filter=ldap_filter)
# SECURE: Explicit character escaping
import ldap3.utils.conv
username = request.form['username']
# Safe: Escapes (, ), *, \, and NUL bytes.
safe_username = ldap3.utils.conv.escape_filter_chars(username)
ldap_filter = f"(&(uid={safe_username})(password={password}))"
ldap_conn.search(search_filter=ldap_filter)
An internal corporate portal allows employees to log in using their Windows credentials via LDAP. An attacker types `admin)(|(&` into the username field and leaves the password blank. The backend generates the filter `(&(uid=admin)(|(&)(password=)))`. Because the OR condition `(|(&))` evaluates to true, the LDAP server ignores the invalid password check, and logs the attacker in as the administrator.
Which of the following characters is NOT a special character that needs escaping in an LDAP search filter?