Safeguard
AppSec

LDAP Injection Attacks: How They Work and How to Prevent Them

LDAP injection lets an attacker manipulate directory-service queries by inserting special filter characters into user input, often bypassing authentication entirely — here's how the attack works and how to stop it.

Safeguard Research Team
Research
6 min read

LDAP injection attacks happen when an application builds an LDAP (Lightweight Directory Access Protocol) search filter by concatenating raw user input into the filter string, letting an attacker insert special characters — parentheses, asterisks, ampersands — that change the query's logic. In the worst cases this lets an attacker bypass a login form entirely by turning a filter that should match "this user with this password" into one that matches "any user," because the directory server evaluates whatever filter syntax it receives, not what the developer intended. LDAP backs authentication for a huge share of corporate identity systems — Active Directory, OpenLDAP, and countless single sign-on integrations — so a single unescaped filter can expose the exact system meant to be the first line of defense.

What is LDAP injection, exactly?

LDAP injection is the directory-service equivalent of SQL injection: instead of manipulating a SQL WHERE clause, the attacker manipulates an LDAP search filter, which uses its own syntax of parentheses and boolean operators like & (AND), | (OR), and ! (NOT). A typical login-lookup filter looks something like (&(uid=USERNAME)(userPassword=PASSWORD)). If the application drops user-supplied input straight into that template without escaping, an attacker who submits a crafted username containing extra parentheses and wildcard characters can restructure the filter's boolean logic so it matches every entry in the directory instead of just one — effectively an authentication bypass achieved purely through query manipulation, no password guessing required.

Why does LDAP injection still show up in modern applications?

It keeps showing up because LDAP filter construction rarely gets the same scrutiny as SQL, even though the underlying flaw is identical: untrusted input concatenated into a query language. OWASP has tracked LDAP injection as a named entry under its Injection category for years (MITRE catalogs the weakness as CWE-90), and it appears in directory-integration code precisely because those integrations are often bolted on late in a project — added for single sign-on or corporate authentication after the core application already exists — and get less security review than the primary data layer. Many frameworks also ship excellent parameterized-query support for SQL but leave LDAP filter-building to hand-rolled string formatting, which is where the vulnerability creeps in.

A related but distinct class is blind LDAP injection, where the attacker can't see query results directly but can still infer information — such as whether a given directory attribute exists or matches a guessed value — by observing differences in application behavior (login success vs. failure, response timing, error messages). This mirrors blind SQL injection techniques and lets a patient attacker enumerate usernames or attribute values one boolean question at a time.

How do attackers actually exploit an injectable LDAP filter?

The two most common LDAP attacks target authentication bypass and information disclosure. In an authentication bypass, the attacker crafts input that forces the filter to always evaluate true, regardless of the actual credentials supplied — the classic technique is injecting a wildcard combined with boolean operators so the filter effectively becomes "match this user OR match anything." In an information-disclosure attack, the attacker abuses a search feature (like a directory lookup or "find user" form) to inject filter operators that pull back attributes or entries the application never intended to expose, including entries outside the expected search scope if the base DN or scope isn't also locked down server-side.

A second category worth understanding involves LDAP filters used for authorization checks rather than authentication — for example, a filter that checks group membership before granting access to a resource. If that filter is injectable, an attacker can potentially manipulate it to appear as a member of an administrative group without ever touching the authentication path at all.

How do you actually prevent LDAP injection?

You prevent it the same way you prevent SQL injection: never build a filter by concatenating raw user input, and escape every special character LDAP treats as syntax before it reaches the query. The characters that need escaping in LDAP filter values include the parenthesis characters, the asterisk (*), the backslash, and the null byte, per RFC 4515's filter escaping rules. Most mainstream LDAP client libraries — including Java's javax.naming ecosystem, .NET's System.DirectoryServices, and Python's ldap3 — provide filter-escaping helper functions specifically for this purpose; use them rather than hand-writing an escape routine, since getting escaping rules wrong is exactly how filter injection slips through in the first place.

Beyond escaping, apply the same defense-in-depth practices that mitigate injection generally: validate input against a strict allow-list where the expected format is known (usernames are rarely legitimate use cases for parentheses or asterisks), enforce least-privilege bind accounts so a successful injection can't read or modify more of the directory than strictly necessary, and log and alert on LDAP filter syntax errors, since a spike in malformed filters is often the first sign someone is probing for an injection point. Static analysis tools that flag string concatenation flowing into directory-search calls can catch this class of bug well before it reaches production — the same reachability-aware review that teams already apply to SQL injection sinks maps directly onto LDAP filter sinks.

How Safeguard Helps

Safeguard's static analysis flags unsanitized input flowing into LDAP filter construction the same way it flags SQL injection sinks, tracing the data path from an HTTP parameter or form field through to the vulnerable API call so a reviewer isn't left guessing whether a flagged concatenation is actually reachable by an attacker. See the SAST/DAST product page for how Safeguard combines static taint tracing with dynamic testing to catch injection classes like this one before release. For a broader look at how this compares to competitor tooling, see our Snyk comparison.

FAQ

Is LDAP injection the same as SQL injection?

No, but they're conceptually identical — both stem from concatenating untrusted input into a query language without escaping. LDAP injection targets directory search filters (parentheses, &, |, !, *) instead of SQL's clause syntax.

Can LDAP injection bypass login forms?

Yes — a classic LDAP injection attack crafts a username or password field so the resulting filter always evaluates true, letting an attacker authenticate as an arbitrary or first-matching directory entry without knowing valid credentials.

What characters need escaping to prevent LDAP injection?

RFC 4515 defines the LDAP filter escaping rules; the characters requiring escaping include (, ), *, the backslash, and the null byte. Use your LDAP client library's built-in escaping function rather than writing this logic by hand.

Does parameterizing LDAP queries work like parameterized SQL queries?

Not identically — LDAP doesn't have a universal prepared-statement API the way SQL does — but most modern LDAP libraries provide filter-building helpers that escape values automatically, which serves the same purpose as SQL parameterization: separating query structure from user-supplied data.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.