ADDOM-012: DNS Zone Security

Platform
Active Directory
Category
AD Domain & Forest Configuration
Severity
High
Zero Trust pillar
Governance (weight 1)
Golden fixtures
3
Branch coverage
Observed: fixtures prove the verdicts they exercise
Provenance
baseline

What it checks

Guerrilla queries the MicrosoftDNS container in the directory under CN=MicrosoftDNS,DC=DomainDnsZones,DC=<domain>,DC=<tld> and CN=MicrosoftDNS,DC=ForestDnsZones,DC=<domain>,DC=<tld>, and additionally the legacy CN=MicrosoftDNS,CN=System,DC=<domain>,DC=<tld> partition for older domains. For each dnsZone object it reads: - name (the zone FQDN, for example contoso.com or _msdcs.contoso.com) - distinguishedName (so the operator can see which partition holds the zone) - dnsProperty (a multi-valued binary attribute that stores DNS_RPC_RECORD_DS structures, including the dwAllowUpdate property at ID 0x00000002) The dnsProperty entry with ID 0x02 encodes the dynamic update mode as a 32-bit integer: 0 = none, 1 = nonsecure and secure, 2 = secure only. Guerrilla parses the binary structure and reports the decoded mode per zone. In parallel the check enumerates Get-DnsServerZone on every reachable DC via WMI (root/MicrosoftDNS) or the DnsServer module to cross-check the directory value against the live server configuration, surfacing any drift. Finally it inspects the DACL on each dnsZone object: by design CREATOR OWNER and Authenticated Users have Create All Child Objects on AD-integrated zones with secure updates enabled, which means any authenticated principal can still create a previously nonexistent dnsNode record (the ADIDNS spoofing primitive documented by Kevin Robertson). The check flags zones where ACLs grant write or modify rights to non-default principals or where Authenticated Users have been granted explicit rights beyond the default.

Why it matters

DNS is the lookup layer for every Kerberos and NTLM authentication exchange. A workstation that resolves dc01.contoso.com sends its AS-REQ and TGS-REQ to whatever IP DNS returns. An attacker who can write or overwrite a DNS record can therefore redirect authentication traffic to a host they control and capture, relay, or downgrade the credential exchange. Nonsecure dynamic updates remove the only barrier in front of that primitive: with dwAllowUpdate = 1 any unauthenticated host on the network can register a record for wpad.contoso.com, dc01.contoso.com, or any service principal name target. The attacker does not need a domain account, does not need to be inside the directory, and does not need to bypass any ACL. Even with secure updates only (the recommended state), the default DACL on the zone still permits Authenticated Users to create new records (but not overwrite existing ones), which is the basis of Kevin Robertson ADIDNSearch primitive and the dirkjanm mitm6 + krbrelayx chain: an attacker registers a previously nonexistent name such as wpad.contoso.com (Windows does not register WPAD by default) and uses it to coerce SMB and HTTP authentication from clients, then relays the credentials to LDAP, LDAPS, ADCS web enrollment, or SMB. The blast radius is the entire domain. Successful DNS spoofing of a Domain Controller record allows Kerberos ticket replay, NTLM relay to LDAP (resulting in RBCD takeover of computer objects), or relay to ADCS HTTP enrollment (ESC8, full domain compromise via PetitPotam style coercion). DNS poisoning is also the entry point for cleartext credential harvesting through Responder when WPAD is registered, and for downgrade attacks that strip Kerberos and force NTLM. Misconfigured DNS zones invalidate every downstream authentication control: SMB signing, LDAP channel binding, and Extended Protection for Authentication all assume the client reaches the legitimate server.

Attack path

1. Reconnaissance. The attacker enumerates AD-integrated zones from any authenticated context using Get-DnsServerZone (DnsServer module), adidnsdump (dirkjanm), or a raw LDAP query against CN=MicrosoftDNS,DC=DomainDnsZones,DC=contoso,DC=com filtered on (objectClass=dnsZone). The dynamic update mode is read from dnsProperty. 2. Record injection (nonsecure path). If dwAllowUpdate = 1, the attacker uses nsupdate (BIND tools) or Invoke-DNSUpdate (Kevin Robertson, Powermad) without any authentication to register a record. Example: nsupdate <<< "server dc01.contoso.com\nupdate add wpad.contoso.com 60 A 10.0.0.66\nsend". The DC accepts the update and replicates it across the domain. 3. Record injection (secure path). If dwAllowUpdate = 2, the attacker authenticates as any domain user and uses Invoke-DNSUpdate -DNSType A -DNSName wpad.contoso.com -DNSData 10.0.0.66 -Realm contoso.com -Username user1 -Password pass. Because CREATOR OWNER has full control over records they create, and the zone DACL allows Authenticated Users to add new records, the operation succeeds for any name that does not already exist. 4. Name resolution coercion. The attacker stands up Responder, ntlmrelayx (Impacket), or krbrelayx on 10.0.0.66 and waits. Clients querying wpad.contoso.com to discover a proxy autoconfig file send NTLM credentials to the attacker. Alternative coercion vectors: mitm6 replies to DHCPv6 with a rogue IPv6 DNS server, then resolves any name to the attacker without writing to ADIDNS at all (mitm6 sidesteps the DNS zone entirely but is in the same attack family). 5. Relay and escalation. Captured NTLM authentications are relayed by ntlmrelayx to LDAP (writing msDS-AllowedToActOnBehalfOfOtherIdentity for RBCD, then S4U to Domain Admin), to ADCS web enrollment (ESC8 certificate for the relayed account), or to SMB on a high-value host. With Domain Controller authentication captured, the attacker can perform DCSync immediately. 6. Persistence. The attacker leaves the rogue DNS record in place. Because secure-only zones grant the creator ownership of the new record, the attacker (as any domain user) retains the ability to delete and re-create the record indefinitely. Defenders who do not audit dnsNode objects in the zone partitions miss the persistence vector entirely. The full chain requires no zero-day. Tooling (mitm6, ntlmrelayx, Invoke-DNSUpdate, krbrelayx, Responder, Inveigh) is publicly maintained and runs from any domain-joined workstation or any host on the local network for the nonsecure path.

How Guerrilla assesses it

Guerrilla resolves the DomainDnsZones and ForestDnsZones application partitions via (Get-ADRootDSE).namingContexts and enumerates every (objectClass=dnsZone) child of CN=MicrosoftDNS in each partition. The legacy CN=System,DC=contoso,DC=com partition is also walked for pre-application-partition zones still in use. For each zone object the check reads dnsProperty and parses the DNS_PROPERTY structure: the entry with ID 0x02 holds the AllowUpdate mode (uint32), and the entry with ID 0x08 holds the AgingState. The decoded value is compared against the constant 2 (DSPROPERTY_ZONE_ALLOW_UPDATE_SECURE). Any zone with a value of 0 (none, manual zone, ACL writability becomes the question) or 1 (nonsecure and secure) fails the check. As a secondary signal the check connects to each domain controller via Get-DnsServerZone (DnsServer module, requires PowerShell remoting or RSAT) and compares the live DynamicUpdate property against the directory value, flagging drift between server-side configuration and the AD-integrated state. The DACL on each zone object is read via Get-Acl AD:\<DN> and inspected for non-default ACEs: the baseline ACEs are NT AUTHORITY\Authenticated Users with Create Child (dnsNode), NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS with full control, BUILTIN\Administrators with full control, and SYSTEM with full control. Any ACE granting Write Property, Write DACL, or Generic All to a non-tier-0 principal is reported. The check also checks the WPAD and ISATAP query block list on each DC (Get-DnsServerGlobalQueryBlockList) because that list is the supported mitigation for WPAD and ISATAP record poisoning. A zone that passes dwAllowUpdate but where the DC has removed wpad and isatap from the global query block list is still vulnerable to the dirkjanm attack chain.

Recommended value

Secure dynamic updates only on all AD-integrated DNS zones

Remediation

Open DNS Manager > Right-click each AD-integrated zone > Properties > General tab > Change Dynamic Updates to 'Secure only'. Review all forward and reverse lookup zones. Verify DNSSEC signing if applicable

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.

Verdict scenarios for ADDOM-012
ScenarioExpected verdict
cleanPASS
known-badFAIL
throttledNot Assessed

Framework mappings

NIST SP 800-53
SC-20, SC-21
CIS Benchmark
18.5.4
ANSSI
R29
CIS AD Benchmark
1.6.1
MITRE ATT&CK
T1557, T1584.002