LDAP Injection
Last updated
Last updated
Room Link: https://tryhackme.com/r/room/ldapinjection
In LDAP, directory entries are structured as objects, each adhering to a specific schema that defines the rules and attributes applicable to the object. This object-oriented approach ensures consistency and governs how objects like users or groups can be represented and manipulated within the directory.
Services that use LDAP:
Microsoft Active Directory: A service for Windows domain networks, utilizing LDAP as part of its underlying protocol suite to manage domain resources.
OpenLDAP: An open-source implementation of LDAP, widely used for managing user information and supporting authentication mechanisms across various platforms.
LDAP entries can be represented using the LDAP Data Interchange Format (LDIF), a standard plain text data format for representing LDAP directory entries and update operations. LDIF imports and exports directory contents and describes directory modifications such as adding, modifying, or deleting entries.
An LDAP directory follows a hierarchical structure like a file system's tree. This structure comprises various entries representing a unique item, such as a user, group, or resource.
At the top of the LDAP tree, we find the top-level domain (TLD), such as dc=ldap,dc=thm
. Beneath the TLD, there may be subdomains or organizational units (OUs), such as ou=people
or ou=groups
, which further categorize the directory entries.
Distinguished Names (DNs): Serve as unique identifiers for each entry in the directory, specifying the path from the top of the LDAP tree to the entry, for example, cn=John Doe,ou=people,dc=example,dc=com
.
Relative Distinguished Names (RDNs): Represent individual levels within the directory hierarchy, such as cn=John Doe
, where cn
stands for Common Name.
Attributes: Define the properties of directory entries, like mail=john@example.com
for an email address.
LDAP search queries are fundamental in interacting with LDAP directories, allowing you to locate and retrieve information stored within the directory. Understanding how to construct these queries is crucial for effectively utilizing LDAP services.
An LDAP search query consists of several components, each serving a specific function in the search operation:
Base DN (Distinguished Name): This is the search's starting point in the directory tree.
Scope: Defines how deep the search should go from the base DN. It can be one of the following:
base
(search the base DN only),
one
(search the immediate children of the base DN),
sub
(search the base DN and all its descendants).
Filter: A criteria entry must match to be returned in the search results. It uses a specific syntax to define these criteria.
Attributes: Specifies which characteristics of the matching entries should be returned in the search results.
The basic syntax for an LDAP search query looks like this:
Filters are the core of LDAP search queries, defining the conditions that entries in the directory must meet to be included in the search results. The syntax for LDAP filters is defined in RFC 4515, where filters are represented as strings with a specific format, such as (canonicalName=value)
. LDAP filters can use a variety of operators to refine search criteria, including equality (=
), presence (=*
), greater than (>=
), and less than (<=
).
One of the most essential operators in LDAP filters is the wildcard *
, which signifies a match with any number of characters. This operator is crucial for formulating broad or partial-match search conditions.
Simple Filter:
This filter targets entries with a canonical name (cn
) exactly matching "John Doe".
Wildcards:
This filter applies the wildcard operator to match any entry where the cn
begins with "J", regardless of what follows.
Complex Filters with Logical Operators:
For a more complex search query, filters can be used with each other using logical operators such as AND (&
), OR (|
), and NOT (!
).
This filter searches for entries classified as "user" in their object class with a canonical name starting with either "John" or "Jane".
While not commonly exposed directly, LDAP services can be accessible over the network via ports 389 (for unencrypted or StartTLS connections) and 636 (for SSL/TLS connections). When LDAP services are accessible publicly, tools such as ldapsearch
, part of the OpenLDAP suite, can be used to interact with the LDAP server. This tool allows a user to query and modify the LDAP directory from the command line, making it a valuable resource for both legitimate administrative tasks and, potentially, for attackers exploiting LDAP Injection vulnerabilities. For example:
Sample Search Query using ldapsearch
This command uses ldapsearch
to perform a search against an LDAP server located at the vulnerable machine on port 389, starting at the base DN dc=ldap,dc=thm
and using a filter that will search for entries under the organizational unit of People.
LDAP Injection is a critical security vulnerability that occurs when user input is not properly sanitized before being incorporated into LDAP queries. This oversight allows attackers to manipulate these queries, leading to unauthorized access or manipulation of the LDAP directory data.
LDAP Injection exploits the way web applications construct LDAP queries. When user input is directly included in these queries without proper validation or encoding, attackers can inject malicious LDAP statements. This can result in unauthorized access to sensitive information, modification of directory data, or bypassing authentication mechanisms.
The process is analogous to SQL Injection, where malicious SQL statements are injected into queries to manipulate database operations. In LDAP Injection, the malicious code targets LDAP queries instead.
Authentication Bypass: Modifying LDAP authentication queries to log in as another user without knowing their password.
Unauthorized Data Access: Altering LDAP search queries to retrieve sensitive information not intended for the attacker's access.
Data Manipulation: Injecting queries that modify the LDAP directory, such as adding or modifying user attributes.
Making an LDAP Injection attack involves several key steps, from identifying the injection point to successfully exploiting the vulnerability.
This diagram illustrates the interaction between the attacker, the web application, and the LDAP server during an LDAP Injection attack. The attacker submits malicious input to the web application login form, which constructs an LDAP query incorporating this input. The LDAP server then executes the altered query, leading to potential unauthorized access or information disclosure, depending on the nature of the injected payload.
LDAP Injection can be particularly dangerous when exploited within authentication mechanisms. Attackers can manipulate LDAP queries for user authentication to bypass security controls, gaining unauthorised access to applications.
For example, below is a simplified PHP code snippet used in a web application for user authentication against an LDAP server:
This code is vulnerable because it directly inserts user-supplied input ($username
and $password
) into the LDAP query without proper sanitisation or escaping. An attacker can exploit this to inject malicious LDAP filters.
To exploit this vulnerability, an attacker can submit a username with a malicious LDAP filter. For example, the attacker could use a username like *
, which, when inserted into the LDAP query, effectively turns the query into a condition that always evaluates to true, bypassing authentication.
This query will authenticate successfully if there is any user in the LDAP directory, as the injected condition uid=*
will always be evaluated to be true.
Tautology-Based Injection
Tautology-based injection involves inserting conditions into an LDAP query that are inherently true, thus ensuring the query always returns a positive result, irrespective of the intended logic. This method is particularly effective against LDAP queries constructed with user input that is not adequately sanitised. For example, consider an LDAP authentication query where the username and password are inserted directly from user input:
An attacker could provide a tautology-based input, such as *)(|(&
for {userInput}
and pwd)
for {passwordInput}
which transforms the query into:
This query effectively bypasses password checking due to how logical operators are used within the filter. The query consists of two parts, combined using an AND (&
) operator.
(uid=*)
: This part of the filter matches any entry with a uid
attribute, essentially all users, because the wildcard *
matches any value.
(|(&)(userPassword=pwd))
: The OR (|
) operator, meaning that any of the two conditions enclosed needs to be true for the filter to pass. In LDAP, an empty AND ((&)
) condition is always considered true. The other condition checks if the userPassword
attribute matches the value pwd
, which can fail if the user is not using pwd
as their password.
Putting it all together, the second part of the filter (|(&)(userPassword=pwd))
will always be evaluated as true because of the (&)
condition. The OR operator only needs one of its enclosed conditions to be true, and since (&)
is always true, the entire OR condition is true regardless of whether (userPassword=pwd)
is true or false.
Therefore, this results in a successful query return for any user without verifying the correct password, bypassing the password-checking mechanism.
Wildcard Injection
Wildcards (*
) are used in LDAP queries to match any sequence of characters, making them powerful tools for broad searches. However, when user input containing wildcards is not correctly sanitised, it can lead to unintended query results, such as bypassing authentication by matching multiple or all entries. For example, if the search query is like:
An attacker might use a wildcard as input in both uid and userPassword. Using a *
for {userInput}
could force the query to ignore specific usernames and focus instead on the password. However, since a wildcard is also present in the {passwordInput}
, it does not validate the content of the password field against a specific expected value. Instead, it only checks for the presence of the userPassword
attribute, regardless of its content.
This means that the query will return a positive match for any user without verifying that the password provided during authentication matches the stored password. As a result, this effectively bypasses the password-checking mechanism.
To demonstrate a simple LDAP Injection attack, go to http://10.10.113.26/normal.php. Based on the code above, the application constructs an LDAP query for authentication based on user input without proper sanitisation.
An attacker can exploit this by submitting a username and password with a character the application does not anticipate, such as an asterisk (*) for the uid and userPassword attribute value. This makes the condition always evaluates to true, effectively bypassing the password check:
Injected Username and Password:
Resulting LDAP Query Component:
This injection always makes the LDAP query's condition true. However, using just the *
will always fetch the first result in the query. To target the data beginning in a specific character, an attacker can use a payload like f*
, which searches for a uid that begins with the letter f.
Blind LDAP Injection is a more subtle variant of LDAP Injection, where the attacker doesn't receive direct output from the injected payload. Instead, they must infer information based on the application's behaviour. This type of attack is more challenging but can still be used to extract sensitive information from an LDAP directory.
Blind LDAP Injection requires a different approach due to the lack of explicit query results. Attackers must rely on indirect signs, such as changes in application behaviour, error messages, or response timings, to deduce the structure of the LDAP query and the existence of vulnerabilities.
For example, below is the code snippet of http://10.10.113.26/blind.php that uses an LDAP query to check for the existence of a user but only returns a generic error message on failure. The application also checks if the submitted email is the same as the email in the database:
This code is vulnerable to Blind LDAP Injection because it constructs an LDAP filter using unsanitized user input. However, it only provides vague feedback, making it challenging to exploit directly.
To exploit this vulnerability, an attacker can use a technique known as Boolean-based Blind LDAP Injection. The attacker injects conditions into the username field to make the LDAP query true or false, observing the application's behaviour to infer information.
For example, an attacker might try injecting a username like a*)(|(&
, which, when included in the LDAP query, checks for any user with "a" in their uid exists:
Injected Username and Password:
Note: The payload above is the URL-encoded version of the payload a*)(|(&
for username and pwd)
for password. It must be URL-decoded first before using it.
Resulting LDAP Query:
If the application returns "Something is wrong in your password", the attacker can infer that a user with an account that starts with "a" in their uid exists in the LDAP directory. To check for the next character, an attacker can reiterate the payload with the next character, for example:
Injected Username and Password:
Resulting LDAP Query:
This indicates that the next character is not "b". An attacker can automate this kind of check by iteratively guessing the characters of the email by observing the web application's behaviour in response to crafted input, similar to a Boolean-based SQL Injection attack.
Boolean Exploitation: This involves injecting conditions that are evaluated to be true or false and observing the application's response to infer data. For example, if the application behaves differently when the condition is true, the attacker can deduce that the injected condition matches an existing entry in the LDAP directory.
Error-Based Inference: In some cases, specific injections might trigger error messages or peculiar application behaviour, providing clues about the LDAP structure or confirming the success of particular payloads.
To automate the exfiltration of data in the previous task, you can use the Python script below:
The above script iteratively guesses the characters of the email by observing the web application's behaviour in response to crafted input.
Save the Python code above. If you are using AttackBox, the required Python modules have already been installed. Make sure to use python3.9
when using the AttackBox since there are multiple Python installations on it.
Below is the sample command on how to run the automation script:
~/Downloads
Kali
This will immediately show the results of the brute force as shown below:
Use the final payload to log in to http://10.10.113.26/login.php. Make sure to use *
as the password; this will automatically evaluate the search query as true.