A quick primer on LDAP injection
June 1, 2023
0 mins readLightweight Directory Access Protocol (LDAP) is an authentication mechanism for securing web applications. LDAP is popular because it's lightweight and scales easily — features that appeal to developers, but mean that LDAP databases often store large amounts of valuable information. This makes them an attractive target for attackers.
Applications construct LDAP queries derived from user inputs to access and manipulate the information stored in LDAP databases. Ideally, the app should validate and sanitize the user input. However, this does not always occur, leaving these queries vulnerable to LDAP injections.
In this article, we’ll look at how LDAP injection works, the potential consequences of this type of attack, and the various means of strengthening applications against it.
How LDAP injection works
LDAP queries use predicates constructed from special characters — such as quotation marks, asterisks, brackets, and ampersands — to control the query’s meaning. These special characters are called meta-characters. Typically, these inputs undergo sanitization and validation before creating and sending the query to the server. However, in an unsecured environment without sufficient input validation, an attacker can modify the control characters and alter the intended behavior of the query.
For example, a login page asks for a USER
and PASSWORD
to authenticate access to a database using one of the most ubiquitous LDAP implementations — OpenLDAP. The LDAP server uses a search filter like the one below to confirm that the user-provided USER
and PASSWORD
credentials exist in a list of access-approved pairs:
(&(USER=jsmith)(PASSWORD=sec87pD02))
It’s important to note that, because of a technicality within Active Directory Application Mode (ADAM) functions, we cannot split this search query into two filters, i.e., the following:
(USER=jsmith)(PASSWORD=sec87pD02)
OpenLDAP would only process the first filter, ignoring the second one. This is why we need the AND (&) operator to ensure that the search filter evaluates to TRUE
when we enter our credentials correctly.
So, assuming our username/password pair exists in the database, we can successfully authenticate by entering “jsmith” and “sec87pD02” as the username and password, respectively.
However, if an attacker only knows the username jsmith
, they could inject the following attack string into the USER field of the login page:
jsmith)(&))
Therefore, if we don’t sanitize the user input before inserting it into the resulting LDAP search query, the query would appear as follows:
(& (USER=jsmith)(&))(PASSWORD=randomstring))
Essentially, the attacker has completed the first filter that the LDAP server will process. Since the first filter that uses the &
operator evaluates to TRUE
, the script ignores the incorrect password in the second filter, granting access to the database.
The LDAP syntax filter, which queries the active directory, is a primary target for attackers. Malicious actors can use it to pass string values that manipulate the LDAP server to execute specific queries and other LDAP statements, injecting commands that exploit inappropriate permissions or misconfigurations on the LDAP server. Misconfigured permissions can allow an attacker to access the LDAP directory, compromising the primary LDAP data structure — the directory information tree. Attackers can also modify LDAP statements or the web applications that create these statements from user inputs.
Negative outcomes of LDAP injection attacks
An LDAP injection is a dangerous security breach that can allow unauthorized access to applications and resources, compromising directory information. Attackers can implement LDAP attacks using different methods — each with potentially severe consequences.
Bypass authentication measures
One of the main reasons to use directory services is to authorize and authenticate users. LDAP controls user access to resources and applications that support it. To access an application or resource, a user provides their login credentials, such as username and password, which LDAP compares with the data in the LDAP directory. The user receives authorization to access the resource if the credentials match.
LDAP attacks often attempt to bypass password checks. Malicious actors will construct a code injection that makes the query end after the username. This enables the attackers to request LDAP authentication from the server without inputting the correct password. An attacker can, for example, use the &
, *
, or |
meta-characters to bypass authentication.
LDAP injection attacks to bypass logins can have severe consequences. Attackers can gain access to administrator accounts, leading to data exposure and privacy violations. Ultimately, these attacks can result in complete system compromise, damaged reputations, and financial damages from lawsuits, fines, and loss of business.
Exposed data and resources
An LDAP injection can allow attackers to disclose, modify, insert, or delete sensitive data (about hosts and users) represented in the LDAP tree. LDAP injection attacks affect applications that use LDAP filters to provide shared resources.
A bad actor can inject an LDAP filter code or use an LDAP query to list all the resources in the directory. This can lead to compromised company data, including sensitive information. It can also lead to directory modifications such as deletions or additions. Once a hacker has acquired directory information, they can use sensitive data as leverage in a ransomware attack.
How to harden applications against LDAP injection
The best way we can avoid LDAP injection attacks is to secure our applications against them. By implementing the following best practices, we can keep our applications secure and reduce the severity of any potential LDAP injection attack.
Validate and sanitize user inputs
The primary defense mechanism against LDAP injection attacks is input validation and sanitization. Our application must validate all user inputs in an LDAP query, including POST and GET parameters, cookies, and HTTP headers. The app should also reject any seemingly invalid inputs it encounters. If an input field requires a user to provide an email address, then you can limit the input to periods (.
), letters, numbers, the at sign (@
), plus signs (+
), underscores (_
), and hyphens (-
).
For a client-server application, validating input on the server side is mandatory. On the client side, it’s technically optional — but critical. Server-side validation prevents users from bypassing client-side validation by turning off JavaScript, which would allow an attacker to leak databases and read or modify data. When applications fail to validate user input, they become vulnerable to directory traversal attacks, where attackers can read arbitrary files on an application’s server.
Enforce the principle of least privilege and zero-trust authorization for directory access
The Principle of Least Privilege (PoLP) is a security measure that limits users’ access rights to the minimum needed to access a resource for the shortest time possible. The PoLP ensures that users can write, execute, or read only the resources they need to complete their functions and responsibilities. This guarantees the authorization of all the LDAP queries executed against the LDAP server. In preventing LDAP injection, the PoLP restricts access to the LDAP account that binds the directory in an application.
By minimizing privileges to LDAP binding accounts, we can limit the impact of any successful injection attack. Then, with the zero-trust model, we also define and restrict the period during which the admins can use the elevated privileges. In addition to using passwords, consider integrating multi-factor authentication (MFA) with LDAP. With MFA, LDAP users who sign in to an application must provide a password and an additional verification mechanism.
Escape any variables or LDAP syntax
Another method of preventing LDAP queries is to use framework-provided functions and escaped variables. Attackers can exploit characters like &
, *
, !
, and |
to launch LDAP injection attacks, so we can sanitize user inputs by escaping these special characters. The RFC 2254 has a guide to escaping assertion values in the string representation of LDAP search filters.
Preventing LDAP injection
Attackers often rely on unvalidated user input to trick the LDAP query interpreter into running arbitrary queries. This method alters the intended LDAP query structure, enabling the attacker to gain unauthorized access to sensitive user information.
To prevent LDAP injections, we need to validate and sanitize inputs adequately, use escaped variables, and enforce the PoLP and zero-trust authorization policies. These methods help control access to LDAP binding accounts and minimize the impacts of an LDAP injection attack. Although we can’t eliminate all potential LDAP injection attacks, we can implement these best practices to ensure that our applications and their users’ data remain as secure as possible.