ADIDNS spoofing: one wildcard record that answers for everyone

Any low-privilege domain account can register a wildcard (*) DNS record in AD-integrated DNS and answer every unresolved query on the network. Claim the wildcard yourself, lock down the zone, and quieten the relay paths.

Marko ZivanovicJul 31, 20269 min read

01 The Big PictureFor leadership · no jargon

Okay, so ADIDNS spoofing, the one where the office phone book turns traitor. This guide walks through what the attack actually is, how to check whether your domain allows it (defaults say: it does), and the three moves that shut it down for good.

Active Directory-integrated DNS is the shared phone directory for the whole company, and by default anyone with a desk pass, meaning any domain account at all, is allowed to write new entries in it. That includes a very special entry: a catch-all line that says "for any name not listed, call this number". An attacker writes their own number into that slot, and from then on every misdial, every typo, every extension for a colleague who left years ago rings the attacker's desk first. The attacker answers, cheerfully pretends to be whoever you meant to call, and relays the conversation. That's the entire attack, and the catch-all entry is the wildcard (*) DNS record.

In practice this turns the lowest-privilege account in the building, a phished laptop, a compromised contractor, into a domain-wide man-in-the-middle. Machines that ask for a server that doesn't quite exist get pointed at the attacker instead, hand over credentials, and those credentials get replayed against real servers. It's been a standard pentester move since 2018, the tooling is public and free, and the defaults that allow it haven't meaningfully changed in over thirteen years. The good news it the fix is configuration, not patching. Claim the catch-all slot yourself, stop everyone from writing in the directory, and stop the relayed calls from being accepted. Minutes to a few hours depending on how your DHCP is set up, and the trade-offs (which are real, and we'll cover them honestly) are manageable.

02 Technical BreakdownFor engineers

AD-integrated zones don't store DNS records in files, every record is an object in Active Directory itself, a dnsNode living under CN=MicrosoftDNS in the DomainDnsZones (or ForestDnsZones) application partition. And here's the load-bearing fact: the default access control list on a zone grants the Authenticated Users group the Create all child objects permission. Any authenticated user can add a brand new dnsNode for any name that doesn't already exist, via an ordinary LDAP add request, and the creator gets full control of what they created.

There are two write paths into the zone. The first is DNS dynamic updates (the mechanism your laptops use to register themselves), and the second is direct LDAP object creation. The first matters for a sneaky reason: the Windows dynamic update implementation doesn't process the * character correctly, so you can't smuggle a wildcard in that way. LDAP has no such problem. This is exactly the gap Kevin Robertson's Powermad exploits:

New-ADIDNSNode -Node * -Verbose

Powermad (New-ADIDNSNode), run as any old domain user: adds a wildcard dnsNode pointing at the attacker's machine. The same module ships Disable-ADIDNSNode (tombstones the record, parking it for later), Enable-ADIDNSNode (resurrects it) and Remove-ADIDNSNode (deletes it).

And the Linux equivalent, from Dirk-jan Mollema's krbrelayx:

dnstool.py -u 'DOMAIN\user' -p 'password' --record '*' --action add --data $AttackerIP $DomainController

dnstool.py does the same job over LDAP from off-domain: one low-privilege credential is all it takes.

"But wait", I hear you ask, "our zones are set to secure dynamic updates only, surely that's the protection?" Sadly no, and this is the bit that trips people up. Secure updates only authenticate *who* is updating and enforce ownership on records that *already exist*. If the name doesn't exist yet, an authenticated user can simply create it and becomes its owner. The wildcard doesn't exist by default. Neither does wpad. So the door is wide open even on a "secure only" zone.

What does the wildcard actually buy? Any query the zone can't match explicitly gets answered with the attacker's record: mistyped hostnames, decommissioned servers, machines referenced in old configs, and (if nobody's defined it) WPAD, the proxy auto-discovery name every Windows box asks about. Unlike LLMNR/NBT-NS spoofing, which only works on the local subnet, the wildcard answers domain-wide. Combine it with relay tooling like ntlmrelayx and every one of those stray requests becomes captured or relayed credentials. Two footnotes before we move on: if WINS forward lookup is enabled on the zone it quietly neutralises the wildcard, and attackers can tombstone their record rather than delete it, leaving a parked wildcard any authenticated user can resurrect later. Lovely.

03 Affected

Every supported Windows Server version running AD-integrated DNS with the default zone permissions, which, in my experience and per everyone who tests this stuff, is most of them. The defaults are the problem: as one sysadmin put it on Hacker News, "the security defaults haven't meaningfully changed since 2003".

Exploitation needs one standard domain credential and network access to a domain controller's DNS and LDAP services. No admin rights, no user interaction. Zones set to "Secure only" dynamic updates are just as affected as "Nonsecure and secure" ones, for the reasons above.

What attackers *can't* do is hijack names that already exist and are owned by someone else: your domain root, your real servers, the SRV records. The attack lives entirely in the unclaimed namespace, which is exactly why claiming the wildcard yourself is such an effective counter.

04 Detection

Before we change anything, let's see what we're dealing with. The cheap test first: ask for a name that cannot possibly exist.

Resolve-DnsName -Name "no-such-host-7734.corp.local" -Server dc01.corp.local

On a healthy zone this fails to resolve. If it comes back with an answer, someone has registered a wildcard, and the address in the answer tells you whose machine is doing the intercepting.

adidnsdump -u corp\\auditor --print-zones dc01.corp.local

Any user can dump the entire zone (yes, really). Dump it to records.csv and diff over time; new * nodes and records you don't recognise stand out.

For the proper alerting: the wildcard is created as an AD object, so directory service change auditing catches it. With "Audit Directory Service Changes" enabled and SACLs on the zone objects, Windows Security events 5136/5137 fire with an object DN like DC=*,DC=corp,DC=local,CN=MicrosoftDNS,DC=DomainDnsZones,...; Elastic ships a production rule ("Potential ADIDNS Poisoning via Wildcard Record Creation") that does exactly this match, and their guidance is blunt: a wildcard record created by anyone who isn't your own defensive sinkhole or a sanctioned red team is basically always bad.

The DNS Server audit log (on by default since Server 2012 R2, under Applications and Services Logs > Microsoft > Windows > DNS-Server > Audit) records record creation as event 515 and dynamic-update creations as 519. The Analytical log (off by default) adds event 263 for each dynamic update received, source IP included. One caution: the LDAP path doesn't go through the DNS update protocol at all, so directory auditing is the more reliable tripwire for the wildcard specifically.

05 Remediation

01 Claim the wildcard before someone else does

Any record type occupying the * name blocks an unprivileged user from creating their own, so the fastest mitigation is to create the wildcard yourself as an administrator. If your estate uses DNS suffix search lists, use a TXT record: an A-record wildcard answers short-name queries before the resolver moves on to the next suffix, and real records living in later zones become unreachable by short name (Kevin Robertson confirmed this in testing after the community reported it). If short names and search lists aren't a concern, an A record pointing at a sinkhole like 0.0.0.0 works and has a nice side effect: because DNS now answers those stray queries, they never fall through to LLMNR/NBT-NS, blunting that spoofing vector too.

dnscmd dc01.corp.local /recordadd corp.local * A 0.0.0.0

The classic wildcard creation command (per Microsoft's own wildcard DNS documentation): swap the sinkhole address for yours. In DNS Manager you can do the same by creating a * domain under the zone and adding a blank-named host to it.

While you're there, create a wpad record too, or confirm WPAD is dealt with (see the last step). The Global Query Block List covers wpad and isatap by default, but it has never covered *.

02 Let DHCP do the writing, with a lead-pencil account

Domain-joined Windows clients normally register their own DNS records, and anything not domain-joined (printers, phones, Linux boxes) relies on the DHCP server registering on their behalf. Before you can safely remove write access from the zone, that registration path has to keep working without handing out broad rights: give the DHCP servers a dedicated low-privilege service account (Domain Users membership is enough) in the DHCP DNS credentials settings, use the same account on every DHCP server, and keep everything out of the DnsUpdateProxy group. Records registered through that group get weakened ACLs any authenticated user can hijack (a risk Microsoft documents and Akamai's 2023 DHCP spoofing research demonstrated in unpleasant detail). If you're forced to use the group on DHCP servers that live on DCs, community consensus is to at least harden it:

dnscmd /config /OpenAclOnProxyUpdates 0

Community-recommended hardening for DnsUpdateProxy on DCs; stops proxy-registered records getting open ACLs. The better answer is still a dedicated account outside the group.

For sensitive non-Windows hosts, Akamai's advice is simpler: static DNS records, because no dynamic-update configuration can protect them from spoofing.

03 Remove write access from the zone itself

This is the real fix, and Kevin Robertson's words on it are worth quoting directly: "locking down the zone permissions is the cleanest way to mitigate authenticated user ADIDNS attacks". In DNS Manager (zone Properties, Security tab) or ADSI Edit on the zone object under CN=MicrosoftDNS, remove the Create all child objects permission for Authenticated Users (and check for any other overly broad principals while you're in there). Do this *after* the DHCP step above, or clients that self-register will silently stop registering.

Worth being precise about why this step matters: it closes the LDAP write path, which the dynamic update settings don't touch at all. A zone can have dynamic updates fully disabled and still accept a wildcard via LDAP if the DACL allows it.

04 Turn dynamic updates off where nothing should be registering

For zones where no client legitimately registers records, remove the dynamic update surface entirely:

Set-DnsServerPrimaryZone -Name "corp.local" -DynamicUpdate None

Accepted values are None, Secure and NonsecureAndSecure (Microsoft Learn). Remember the caveat above: this alone doesn't close the LDAP path, the DACL step does.

05 Quieten the relay paths

Even with the wildcard claimed and the zone locked down, the credentials an attacker does manage to catch shouldn't be replayable. Enforce SMB signing, require LDAP signing and channel binding, disable LLMNR and NBT-NS, and either disable WPAD outright or configure an explicit proxy PAC URL. And if you're not actively using IPv6 internally, disable it: Fox-IT's mitm6 research showed a rogue IPv6 DNS server achieves the same man-in-the-middle without touching ADIDNS at all, and their conclusion still stands: the only complete defence against mitm6 is not offering DHCPv6 answers to attack in the first place.

06 Verification

Patched and locked down? Let's prove it rather than assume it.

Resolve-DnsName -Name "no-such-host-7734.corp.local" -Server dc01.corp.local

If you deployed a TXT wildcard this still fails to resolve (the name exists but has no A record); with an A sinkhole it resolves to your sinkhole address. Either way it must never resolve to something you don't own.

Get-DnsServerZone | Where-Object IsDsIntegrated | Select-Object ZoneName, DynamicUpdate

Expect Secure, or None where you disabled updates. NonsecureAndSecure has no business being here.

Then the ownership check: in DNS Manager or ADSI Edit, confirm the * node's owner is your administrative account, not a random user. And the definitive test, in a lab or with change control: try New-ADIDNSNode -Node * -Verbose as an ordinary domain user. After the DACL lockdown it should fail outright. If it succeeds, the zone permissions didn't take.

07 Rollback

The realistic rollback is DNS registration breaking after the DACL lockdown, almost always because the DHCP credential step was skipped or half-done. Restore secure dynamic updates while you fix it properly:

Set-DnsServerPrimaryZone -Name "corp.local" -DynamicUpdate Secure

Back to the default behaviour while you sort the DHCP service account; re-apply the DACL lockdown once registration flows through it.

If the defensive wildcard itself causes pain in a multi-suffix environment (short names resolving to the sinkhole instead of a record in a later search-list zone), swap the A record for a TXT wildcard, which blocks attackers without answering A queries. Removing the wildcard entirely is acceptable only if the zone DACL is locked down *and* the 5136/5137 alerting is in place; otherwise you've reopened the front door to save a side window.

Re-granting Authenticated Users the create-child permission is the full undo (same Security tab you edited), but treat it as what it is: deliberately returning to the exploitable default.

08 References

If I've got anything wrong here, or you've hit an edge case I haven't covered, do say, corrections and questions are always welcome :)

// Patched, or stuck?

Ship the fix. Prove it’s closed.

If this runbook doesn’t fit your stack, send the CVE — an operator writes a verified path, usually within a business day. Or contribute your own and get co-authored credit.

// Dispatch

New guides, straight to your inbox.