Learn Pentesting: Manual Testing for LDAP Injection

In this post, we explore LDAP injection from a penetration tester’s perspective. As part of our “Learn Pentesting” series, this article delves into the technical nuances of identifying, testing, and understanding LDAP injection vulnerabilities. Whether you’re new to penetration testing or looking to refine your skills, this guide will serve as a comprehensive reference.


Introduction

LDAP (Lightweight Directory Access Protocol) injection is a web application vulnerability that occurs when user input is unsafely incorporated into LDAP queries. Much like SQL injection, attackers can manipulate the logic of LDAP queries to bypass authentication, enumerate directory information, or even modify directory data if the application provides such functionality.

In this technical deep-dive, we will:


Understanding LDAP Injection

What is LDAP Injection?

LDAP injection exploits the way an application constructs LDAP queries. Typically, an application might build an LDAP filter string by concatenating a fixed query pattern with user-supplied input. If the input isn’t sanitized or parameterized properly, an attacker can insert special characters or additional LDAP operators to alter the query’s logic.

Example Scenario:

Consider an application that constructs an LDAP query to authenticate users:

(&(uid={user_input})(objectClass=person))

If the input isn’t validated, an attacker might supply:

*)(|(uid=*)) 

This payload transforms the original query into:

(&(uid=*)(|(uid=*)) (objectClass=person))

The injection effectively bypasses the intended filtering, potentially returning more entries than expected or granting unauthorized access.


Manual Testing Methodology

When manually testing for LDAP injection vulnerabilities, follow these steps:

  1. Identify Input Vectors:
    Look for user input fields that might be used to construct LDAP queries. Common examples include login forms, search boxes, or any functionality that interacts with a directory service.

  2. Understand the Query Construction:
    If possible, review the source code or backend logic to see how the input is incorporated into the LDAP query. Often, vulnerabilities exist when user input is concatenated into the LDAP filter without proper sanitization.

  3. Inject Malicious Payloads:
    Start with benign test inputs to determine the behavior of the application. Then, gradually introduce payloads to test if the query logic can be manipulated. Watch for error messages, unexpected behavior, or directory information leakage.

  4. Analyze Responses:
    Error messages or abnormal responses (e.g., a sudden increase in returned entries) can indicate that LDAP query structure has been disrupted.

  5. Document Findings:
    Capture all requests and responses to help demonstrate the vulnerability, and use this data to propose effective remediation.


Payload Examples

Here are some common payloads to try during testing:

Always begin testing in a controlled environment and with explicit permission, as these tests can trigger extensive data exposure.


Demonstration: Exploiting LDAP Injection with Python

Below is an example Python script using the ldap3 library that demonstrates how an attacker might test for LDAP injection manually. This script simulates constructing an LDAP query from user input and then injecting a malicious payload.

import ldap3

def test_ldap_injection(server_url, bind_dn, bind_password, base_dn, user_input):
    # Connect to the LDAP server
    server = ldap3.Server(server_url)
    conn = ldap3.Connection(server, user=bind_dn, password=bind_password, auto_bind=True)

    # Vulnerable filter construction: input is directly embedded in the filter string.
    ldap_filter = f"(&(uid={user_input})(objectClass=person))"
    print("Testing LDAP Filter:", ldap_filter)

    try:
        # Execute search query using the crafted LDAP filter.
        conn.search(base_dn, ldap_filter, attributes=['uid', 'cn'])
        print("Search Results:")
        for entry in conn.entries:
            print(entry)
    except Exception as e:
        print("Error during LDAP search:", e)
    finally:
        conn.unbind()

# Configuration parameters (adjust these based on your test environment)
LDAP_SERVER = 'ldap://localhost'
BIND_DN = 'cn=admin,dc=example,dc=com'
BIND_PASSWORD = 'password'
BASE_DN = 'dc=example,dc=com'

# Normal user input (expected behavior)
normal_input = 'jdoe'
print("=== Testing with Normal Input ===")
test_ldap_injection(LDAP_SERVER, BIND_DN, BIND_PASSWORD, BASE_DN, normal_input)

# Malicious input to test for LDAP injection vulnerability
malicious_input = "*)(|(uid=*))"
print("\n=== Testing with Malicious Input ===")
test_ldap_injection(LDAP_SERVER, BIND_DN, BIND_PASSWORD, BASE_DN, malicious_input)

Explanation of the Code


Detection and Exploitation

During manual testing, keep an eye out for:

Leveraging tools such as Burp Suite can automate parts of this process; however, manual testing remains crucial for understanding the underlying mechanics and potential impact of the vulnerability.


Mitigation Strategies

To prevent LDAP injection vulnerabilities:


Conclusion

LDAP injection represents a critical security risk, especially in environments where directory services manage sensitive data. Through careful manual testing and a deep understanding of how LDAP queries are constructed, penetration testers can identify these vulnerabilities before they are exploited by malicious actors.

By integrating these practices into your penetration testing workflow, you can enhance your ability to detect and remediate LDAP injection vulnerabilities effectively.


Stay tuned for more technical deep-dives in our “Learn Pentesting” series as we continue to explore the intricacies of securing modern web applications.

Ready to see how Numorian can help your business?

Contact us today to learn more about our services and how we can support your business.