LDAP
Overview
LDAP (Lightweight Directory Access Protocol) is a protocol used to access and manage directory information. A directory is a hierarchical data store containing information about network resources such as users, groups, computers, printers, and other devices. LDAP runs over TCP/IP (port 389) or SSL/TLS (port 636, LDAPS) and is platform-independent.
Functionality
Strengths
| Feature | Description |
|---|---|
| Efficient | Fast queries and connections thanks to a lean query language and non-normalised data storage |
| Global naming model | Supports multiple independent directories with a global naming model that ensures unique entries |
| Extensible and flexible | Custom attributes and schemas can be defined to meet local or future requirements |
| Compatible | Runs over TCP/IP and SSL directly; platform-independent and compatible with many software products and heterogeneous environments |
| Authentication | Provides authentication mechanisms enabling single sign-on across multiple server resources |
Weaknesses
| Issue | Description |
|---|---|
| Compliance | Directory servers must be LDAP-compliant for deployment, limiting vendor choice |
| Complexity | Difficult to configure and use securely for many developers and administrators |
| Encryption | Does not encrypt traffic by default; LDAPS or StartTLS must be used to prevent eavesdropping |
| Injection | Vulnerable to LDAP injection attacks if input is not properly validated and sanitised |
Common Use Cases
| Use Case | Description |
|---|---|
| Authentication | Central authentication allowing single login credentials across multiple applications and systems |
| Authorisation | Managing permissions and access control for network resources (may require Kerberos integration) |
| Directory Services | Searching, retrieving, and modifying data in a directory; managing large numbers of users and devices. Based on the X.500 standard |
| Synchronisation | Replicating directory changes across multiple systems to keep data consistent |
LDAP vs Active Directory
LDAP and Active Directory are related but serve different purposes. LDAP is a protocol that specifies how to access and modify directory services. Active Directory is a directory service that uses LDAP as one of its protocols.
| LDAP | Active Directory (AD) | |
|---|---|---|
| Type | Protocol defining client-server communication for directory access | Directory server that uses LDAP as one of its protocols |
| Platform | Open, cross-platform, works with many directory servers | Proprietary; Windows-only; requires DNS and Kerberos |
| Schema | Flexible and extensible; custom attributes and object classes | Predefined schema extending X.500; modifications should be made with caution |
| Authentication | Multiple mechanisms: simple bind, SASL, etc. | Kerberos (primary), NTLM, LDAP over SSL/TLS for legacy compatibility |
How LDAP Works
LDAP uses a client-server architecture. Clients send LDAP messages encoded in ASN.1 (Abstract Syntax Notation One) over TCP/IP. Servers process requests and return responses in the same format.
Request Components
| Component | Description |
|---|---|
| Session connection | Client connects via LDAP port (typically 389 or 636) |
| Request type | Operation to perform: bind, search, add, delete, modify, compare, etc. |
| Request parameters | DN of the entry to access, search scope and filter, attributes/values to change |
| Request ID | Unique identifier to match each request with its response |
Response Components
| Component | Description |
|---|---|
| Response type | Operation that was performed |
| Result code | Whether the operation succeeded and why |
| Matched DN | Closest existing entry DN that matched the request, if applicable |
| Referral | URL of another server that may have more information, if applicable |
| Response data | Attributes and values returned (e.g., search results) |
ldapsearch
ldapsearch is a command-line utility for querying LDAP directory services.
Syntax
ldapsearch -H ldap://<server>:<port> -D "<bind_dn>" -w <password> -b "<base_dn>" "<filter>"
Example
ldapsearch -H ldap://ldap.example.com:389 \
-D "cn=admin,dc=example,dc=com" \
-w secret123 \
-b "ou=people,dc=example,dc=com" \
"(mail=john.doe@example.com)"
| Flag | Purpose |
|---|---|
-H ldap://... | Server URI |
-D "cn=..." | Bind DN (account to authenticate as) |
-w <password> | Bind password |
-b "ou=..." | Base DN to search under |
"(filter)" | LDAP search filter |
This command:
- Connects to
ldap.example.comon port 389 - Authenticates as
cn=admin,dc=example,dc=comwith passwordsecret123 - Searches under the base DN
ou=people,dc=example,dc=com - Returns entries matching
(mail=john.doe@example.com)
Example response:
dn: uid=jdoe,ou=people,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: John Doe
sn: Doe
uid: jdoe
mail: john.doe@example.com
result: 0 Success
Anonymous bind (unauthenticated enumeration)
ldapsearch -H ldap://<target>:389 -x -b "dc=example,dc=com"
| Flag | Purpose |
|---|---|
-x | Simple authentication (anonymous bind — no -D or -w) |
LDAP Injection
Overview
LDAP injection is an attack that exploits web applications using LDAP for authentication or user information storage. Malicious characters injected into LDAP queries can alter query behaviour, bypass authentication, and expose directory data.
It is analogous to SQL injection but targets directory services rather than databases.
Special Characters
| Input | Effect |
|---|---|
* | Wildcard — matches any number of characters |
( ) | Group expressions |
| | Logical OR |
& | Logical AND |
(cn=*) | Always-true condition — useful for auth bypass |
Vulnerable Query Example
An application using the following LDAP query for authentication:
(&(objectClass=user)(sAMAccountName=$username)(userPassword=$password))
Bypass via username wildcard
Injecting * as the username makes the query match any user account:
$username = "*"
$password = "dummy"
Resulting query:
(&(objectClass=user)(sAMAccountName=*)(userPassword=dummy))
This matches any account whose password is dummy — or in misconfigured servers, any account at all.
Bypass via password wildcard
Injecting * as the password matches any password:
$username = "dummy"
$password = "*"
Resulting query:
(&(objectClass=user)(sAMAccountName=dummy)(userPassword=*))
This matches the dummy account with any password.
Consequences
- Unauthorised access to sensitive data
- Privilege escalation
- Full control over the application or server
- Data integrity risks (attackers may alter or delete directory entries)
Mitigations
- Validate and sanitise all user input before incorporating it into LDAP queries
- Remove or escape LDAP special characters (
*,(,),\,NUL) from input - Use parameterised queries so user input is treated as data, not executable code
- Enforce least-privilege bind accounts
Enumeration
Nmap
nmap -p- -sC -sV --open --min-rate=1000 <target>
Example output:
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
389/tcp open ldap OpenLDAP 2.2.X - 2.3.X
Port 389 (LDAP) open alongside a web application on port 80 is a strong indicator that the web app uses LDAP for authentication — a candidate for LDAP injection testing.
Exploitation — Authentication Bypass
When a web application uses LDAP for authentication and does not sanitise input, injecting the wildcard * into both the username and password fields can bypass the authentication check entirely.
Payload:
Username: *
Password: *
This causes the application’s LDAP query to match any user with any password, granting access without valid credentials.
This is the LDAP equivalent of the classic SQL injection ' OR '1'='1 authentication bypass.