ADDOM-014: LDAP Channel Binding
- Platform
- Active Directory
- Category
- AD Domain & Forest Configuration
- Severity
- High
- Zero Trust pillar
- Governance (weight 2)
- Golden fixtures
- 3
- Branch coverage
- Observed: fixtures prove the verdicts they exercise
- Provenance
- baseline
What it checks
Guerrilla reads HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Parameters\LdapEnforceChannelBinding on every domain controller in the forest. The value is a DWORD with three documented states: 0 = Disabled (no validation), 1 = When Supported (validate only if the client advertises support, which means downlevel clients pass through unprotected), 2 = Always (every channel-binding-capable bind must include a correct CBT and binds without one are rejected). The check fails when the value is absent, 0, or 1. The cmdlet also enumerates Event 3039 / 3040 / 3041 occurrences from the Directory Service log over the previous seven days to confirm whether the DC has observed bind attempts that would have been blocked under "Always" mode, which lets an operator stage the rollout safely.
Why it matters
LDAP over SSL/TLS (LDAPS on 636 and LDAP+StartTLS on 389) is the channel used by most modern AD tooling, but the TLS layer alone only protects confidentiality of the bytes on the wire. It does nothing to prevent an attacker from terminating one TLS session, authenticating to a second TLS session against a DC, and proxying the inner SASL bind. Channel binding closes that gap by including the hash of the DC TLS certificate (the tls-server-end-point endpoint channel binding) in the authenticator the client signs. A relay cannot produce a valid CBT for a certificate it does not control, so the DC rejects the relayed bind. Without CBT enforcement, well known attack chains such as PetitPotam to ADCS HTTP endpoints, WebDAV coercion via PrinterBug or DFSCoerce, and any NTLM-relay primitive that lands a relayed bind on LDAPS will succeed and let the attacker make directory writes (RBCD, shadow credentials, AdminSDHolder ACL edits) as the coerced principal. Microsoft has shipped the toggle since the March 2020 hardening release (ADV190023) and announced that channel binding is enforced by default beginning with the 2024 hardening wave on Windows Server 2025 DCs, but every legacy DC retains the permissive default until the registry value is set explicitly.
Attack path
1. Attacker lands a foothold inside the network (phish, vulnerable web app, rogue device on subnet). 2. Attacker starts an NTLM relay listener, typically ntlmrelayx.py from impacket, with the target set to ldaps://dc.contoso.local and a relay action such as --escalate-user or --shadow-credentials. 3. Attacker triggers authentication coercion from a high-value account or computer object: PetitPotam (MS-EFSRPC EfsRpcOpenFileRaw) against any host with the EFS RPC interface, PrinterBug (MS-RPRN RpcRemoteFindFirstPrinterChangeNotificationEx) against the spooler, or DFSCoerce (MS-DFSNM NetrDfsRemoveStdRoot) against any DFS-N server. 4. The coerced machine account opens an authenticated connection to the relay over SMB or HTTP. 5. The relay forwards the inner NTLM exchange to the DC over LDAPS. With channel binding disabled, the DC accepts the bind as the coerced computer or user. 6. The attacker uses the now-authenticated LDAPS session to write msDS-KeyCredentialLink (Shadow Credentials, T1556.007), set msDS-AllowedToActOnBehalfOfOtherIdentity (Resource Based Constrained Delegation, T1134.001), or, if the relayed identity is a Domain Admin or DC machine account, perform DCSync (T1003.006). With LdapEnforceChannelBinding = 2 the DC rejects the relayed bind with LDAP error 8009030C (SEC_E_BAD_BINDINGS) and the entire chain breaks at the LDAPS hop.
How Guerrilla assesses it
Guerrilla queries each DC via remote registry (Get-ItemProperty on HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters) and records LdapEnforceChannelBinding alongside LDAPServerIntegrity for context. It then opens the Directory Service event log on the same DC and counts Event 3039 (a client did not present CBT when the DC required it), 3040 (a summary of clients that performed unprotected binds in the last 24 hours), and 3041 (a client that would fail under Always mode) over the previous seven days. The combination tells the operator three things at once: whether enforcement is on, whether clients exist that still cannot do CBT, and which clients those are by source IP. The check fails when the registry value is missing or below 2 on any DC, and it surfaces the per-client breakdown so the operator can remediate the offending clients before flipping the switch.
Recommended value
LDAP channel binding set to 'Always' on all domain controllers
Remediation
Set the registry value LdapEnforceChannelBinding to 2 (Always) at HKLM\System\CurrentControlSet\Services\NTDS\Parameters on all DCs. Test with value 1 (When Supported) first to identify incompatible clients
Fixture-proven verdicts
Every verdict below is proven by a golden fixture in the module's gating test suite. This table derives from the last green run; it cannot be edited by hand.
| Scenario | Expected verdict |
|---|---|
| clean | PASS |
| known-bad | FAIL |
| throttled | Not Assessed |
Framework mappings
- NIST SP 800-53
- SC-8, SC-8(1), SC-23
- CIS Benchmark
- 18.3.5
- ANSSI
- R25
- NSA / ASD
- LDAP-2
- CIS AD Benchmark
- 2.1.2
- MITRE ATT&CK
- T1557