Skip to content

AD-INF-005: LDAP signing not required

medium   Infrastructure   MITRE ATT&CK T1557   Reads: LDAP probe

A domain controller accepts an unsigned NTLM bind on plain LDAP, so authentication relayed from a coerced host can be used to modify the directory.

Also known as: ldap-signing

Why it matters

When a DC does not require LDAP signing, an NTLM authentication captured anywhere can be relayed to its plain LDAP port and used as the victim. Attackers get that authentication for free: PetitPotam, PrinterBug and similar coercion bugs make a server authenticate to a host of the attacker's choice, and WebDAV or name-resolution poisoning collects it from workstations.

Relayed to LDAP, a computer account's authentication can write msDS-AllowedToActOnBehalfOfOtherIdentity on itself (resource-based delegation, then local admin on that server) or msDS-KeyCredentialLink (shadow credentials); a relayed administrator can add accounts to privileged groups. One DC that does not require signing is enough, because the attacker chooses which DC to relay to.

How ad-doctor detects it

ad-doctor performs an NTLM bind without signing on the plain LDAP port of each DC (--signing-probe-port, 389 by default). A DC that requires signing rejects it with strongerAuthRequired (result 8); a successful bind means it does not. Any other answer is inconclusive and is written to the scan notes, not reported.

The probe needs a DOMAIN\user account with a password (NTLM); it is skipped with a note when scanning with Kerberos. By default every enabled DC in the domain is probed by its dNSHostName; --single-dc limits it to the DC being scanned. Each object is a DC host name, for example DC01.adlab.test, and the detail says how many of the probed DCs failed.

Attributes and probes read
  • LDAP bind result (strongerAuthRequired)

Severity

Always medium on its own. Combined with a machine account quota above 0 it is part of the relay-to-RBCD chain reported as high by AD-CHAIN-001.

False positives and limits

None expected: the probe observes the DC's actual behaviour. A DC that could not be reached is not reported here; see AD-INF-013.

Fix

  1. Find clients that still bind without signing before enforcing: on each DC, raise the LDAP interface event logging (16 LDAP Interface Events = 2) and collect event 2889 for a few days.
  2. Require signing on every DC through the Default Domain Controllers Policy: Computer Configuration > Policies > Windows Settings > Security Settings > Local Policies > Security Options > Domain controller: LDAP server signing requirements = Require signing. The setting lands in the registry; read it to confirm:

    Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters' -Name LDAPServerIntegrity
    # 2 = require signing; set it through the GPO rather than by hand:
    Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters' `
        -Name LDAPServerIntegrity -Value 2 -WhatIf
    
  3. Enforce LDAPS channel binding as well (AD-INF-010): signing protects plain LDAP only.

  4. Set ms-DS-MachineAccountQuota to 0 (AD-POL-002) to take away the easiest follow-up of a successful relay.

Verify

ad-doctor scan dc01.corp.example --ldaps -u 'CORP\auditor' --only AD-INF-005

To accept the risk instead, add an entry to the file passed with --accept (see accepted risks):

[[accept]]
check = "AD-INF-005"
objects = ["..."]        # optional; without it the whole check is accepted
reason = "..."
expires = 2027-03-31

References

Microsoft and vendors

Research

MITRE ATT&CK

Available since 0.1.0.