identity access management

Configuring LDAP Security Hardening

Harden LDAP directory services against common attacks including credential harvesting, LDAP injection, anonymous binding, and channel binding bypass. Covers LDAPS enforcement, channel binding, LDAP signing, access control lists, and monitoring for LDAP-based attacks.

access-controldirectory-serviceshardeningiamidentityldap
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Overview

Harden LDAP directory services against common attacks including credential harvesting, LDAP injection, anonymous binding, and channel binding bypass. Covers LDAPS enforcement, channel binding, LDAP signing, access control lists, and monitoring for LDAP-based attacks.

When to Use

  • When deploying or configuring configuring ldap security hardening capabilities in your environment
  • When establishing security controls aligned to compliance requirements
  • When building or improving security architecture for this domain
  • When conducting security assessments that require this implementation

Prerequisites

  • Familiarity with identity access management concepts and tools
  • Access to a test or lab environment for safe execution
  • Python 3.8+ with required dependencies installed
  • Appropriate authorization for any testing activities

Objectives

  • Implement comprehensive configuring ldap security hardening capability
  • Establish automated discovery and monitoring processes
  • Integrate with enterprise IAM and security tools
  • Generate compliance-ready documentation and reports
  • Align with NIST 800-53 access control requirements

Security Controls

Control NIST 800-53 Description
Account Management AC-2 Lifecycle management
Access Enforcement AC-3 Policy-based access control
Least Privilege AC-6 Minimum necessary permissions
Audit Logging AU-3 Authentication and access events
Identification IA-2 User and service identification

Verification

  • Implementation tested in non-production environment
  • Security policies configured and enforced
  • Audit logging enabled and forwarding to SIEM
  • Documentation and runbooks complete
  • Compliance evidence generated
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 1

api-reference.md1.6 KB

LDAP Security Hardening — API Reference

Libraries

Library Install Purpose
ldap3 pip install ldap3 LDAP protocol client for security auditing

Key ldap3 Methods

Method Description
Server(ip, port, use_ssl, tls, get_info=ALL) Create LDAP server with TLS config
Connection(server, user, password, authentication=NTLM) Authenticated bind
Connection(server, auto_bind=True) Anonymous bind test
conn.search(base, filter, attributes) Search directory objects

LDAP Security Settings (GPO)

Setting Registry Path Recommended Value
LDAP Signing HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Parameters\LDAPServerIntegrity 2 (Require)
Channel Binding HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Parameters\LdapEnforceChannelBinding 2 (Always)
Simple Bind GPO: Network security: LDAP client signing requirements Require signing

Security Checks

Check Risk Severity
Anonymous bind allowed User/group enumeration CRITICAL
LDAPS not available Cleartext credential transmission HIGH
LDAP signing not enforced NTLM relay via LDAP HIGH
Channel binding disabled Credential relay attacks MEDIUM

External References

Scripts 1

agent.py5.3 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""LDAP security hardening audit agent using ldap3."""

import json
import sys
import argparse
from datetime import datetime

try:
    import ldap3
    from ldap3 import Server, Connection, ALL, NTLM, Tls
    import ssl
except ImportError:
    print("Install: pip install ldap3")
    sys.exit(1)


def check_ldap_signing(server_ip):
    """Check if LDAP signing is enforced."""
    try:
        server = Server(server_ip, port=389, get_info=ALL)
        conn = Connection(server, auto_bind=True)
        info = server.info
        conn.unbind()
        return {
            "check": "LDAP signing",
            "port": 389,
            "anonymous_bind": True,
            "severity": "HIGH",
            "recommendation": "Enforce LDAP signing via GPO: Domain controller: LDAP server signing requirements = Require signing",
        }
    except Exception as e:
        return {"check": "LDAP signing", "error": str(e), "anonymous_bind": False}


def check_ldaps(server_ip):
    """Check LDAPS (LDAP over TLS) availability."""
    try:
        tls = Tls(validate=ssl.CERT_NONE)
        server = Server(server_ip, port=636, use_ssl=True, tls=tls, get_info=ALL)
        conn = Connection(server, auto_bind=True)
        conn.unbind()
        return {"check": "LDAPS", "port": 636, "available": True, "severity": "INFO"}
    except Exception as e:
        return {"check": "LDAPS", "available": False, "severity": "HIGH",
                "recommendation": "Enable LDAPS by installing a certificate on the domain controller"}


def check_channel_binding(server_ip, domain, username, password):
    """Check LDAP channel binding enforcement."""
    try:
        server = Server(server_ip, get_info=ALL)
        conn = Connection(server, user=f"{domain}\\{username}", password=password,
                          authentication=NTLM, auto_bind=True)
        conn.unbind()
        return {
            "check": "Channel binding",
            "simple_bind_allowed": True,
            "severity": "MEDIUM",
            "recommendation": "Enable LDAP channel binding via registry: LdapEnforceChannelBinding=2",
        }
    except Exception as e:
        return {"check": "Channel binding", "error": str(e)}


def audit_anonymous_access(server_ip):
    """Check for anonymous LDAP access and enumeration."""
    findings = []
    try:
        server = Server(server_ip, get_info=ALL)
        conn = Connection(server, auto_bind=True)
        conn.search("", "(objectClass=*)", search_scope=ldap3.BASE, attributes=["*"])
        if conn.entries:
            findings.append({
                "issue": "Anonymous rootDSE access",
                "severity": "MEDIUM",
                "detail": "Server exposes rootDSE information to unauthenticated clients",
            })
        base_dn = server.info.other.get("defaultNamingContext", [""])[0] if server.info else ""
        if base_dn:
            conn.search(base_dn, "(objectClass=user)", attributes=["sAMAccountName"])
            if conn.entries:
                findings.append({
                    "issue": "Anonymous user enumeration",
                    "severity": "CRITICAL",
                    "detail": f"Anonymous bind can enumerate {len(conn.entries)} user objects",
                })
        conn.unbind()
    except Exception as e:
        findings.append({"issue": "Anonymous access test", "error": str(e)})
    return findings


def run_audit(server_ip, domain=None, username=None, password=None):
    """Execute LDAP security hardening audit."""
    print(f"\n{'='*60}")
    print(f"  LDAP SECURITY HARDENING AUDIT")
    print(f"  Target: {server_ip}")
    print(f"  Generated: {datetime.utcnow().isoformat()} UTC")
    print(f"{'='*60}\n")

    signing = check_ldap_signing(server_ip)
    print(f"--- LDAP SIGNING ---")
    print(f"  Anonymous bind: {signing.get('anonymous_bind', 'N/A')}")
    print(f"  Severity: {signing.get('severity', 'N/A')}")

    ldaps = check_ldaps(server_ip)
    print(f"\n--- LDAPS (TLS) ---")
    print(f"  Available: {ldaps.get('available', 'N/A')}")
    print(f"  Severity: {ldaps.get('severity', 'N/A')}")

    anon = audit_anonymous_access(server_ip)
    print(f"\n--- ANONYMOUS ACCESS ({len(anon)} findings) ---")
    for a in anon:
        if "error" not in a:
            print(f"  [{a['severity']}] {a['issue']}: {a.get('detail', '')}")

    if domain and username and password:
        binding = check_channel_binding(server_ip, domain, username, password)
        print(f"\n--- CHANNEL BINDING ---")
        print(f"  {binding.get('check', '')}: {binding.get('severity', '')}")

    return {"signing": signing, "ldaps": ldaps, "anonymous": anon}


def main():
    parser = argparse.ArgumentParser(description="LDAP Security Audit Agent")
    parser.add_argument("--server", required=True, help="LDAP server IP")
    parser.add_argument("--domain", help="AD domain name")
    parser.add_argument("--username", help="LDAP username")
    parser.add_argument("--password", help="LDAP password")
    parser.add_argument("--output", help="Save report to JSON file")
    args = parser.parse_args()

    report = run_audit(args.server, args.domain, args.username, args.password)
    if args.output:
        with open(args.output, "w") as f:
            json.dump(report, f, indent=2, default=str)
        print(f"\n[+] Report saved to {args.output}")


if __name__ == "__main__":
    main()
Keep exploring