DNS server cache snooping means your DNS server answers non-recursive queries for third-party domains from its cache, so anyone who can query it learns which sites and services its users recently looked up. Fix it by limiting cache access to trusted clients (BIND allow-query-cache and allow-recursion), keeping authoritative servers non-recursive, and firewalling Windows DNS resolvers.
What the scanner is actually detecting
The finding is Nessus plugin 12217, “DNS Server Cache Snooping Remote Information Disclosure” (family: DNS, port udp/53, severity Medium). Tenable lists a CVSS v3 base score of 5.3 and a CVSS v2 base score of 5.0. Its description says the remote DNS server responds to queries for third-party domains that do not have the recursion bit set.
That recursion bit (RD, “recursion desired”) is the key. A normal client sets RD and asks the server to go and find the answer. A query with RD cleared asks only “what do you already know?” If the server returns an answer for a domain it is not authoritative for, that answer can only have come from its cache, which means one of its clients looked the name up recently. The plugin is a remote check and exploits nothing.
Tenable’s solution text is simply “Contact the vendor of the DNS software for a fix.” In practice no patch is involved: this is a configuration and network placement issue, and the fixes below are all settings.
Real-world risk, stated honestly
This is an information disclosure issue, not a compromise. An attacker cannot change your cache or run code through it. What they can do is test a list of guessed domain names and see which ones your server has cached, which hints at the services your organization uses. Tenable’s description gives examples such as financial relationships, B2B partners, browsing patterns and external mail servers.
The limits are real too. The attacker has to guess names, a cache hit only proves someone resolved the name within its TTL, and it does not reveal which client did. Tenable notes that for an internal server not reachable from outside, the exposure is limited to the internal network, which may still include consultants and guest Wi-Fi users.
Prioritize accordingly: a server that answers cache queries from the Internet deserves a prompt fix, and it is often also an open resolver, so check whether Nessus reported plugin 10539 (DNS Server Recursive Query Cache Poisoning Weakness) on the same address. An internal resolver answering an internal scanner is usually low priority.
How to confirm it on the host
The cleanest test is “seed, then snoop”. From an internal client, resolve a name normally so it lands in the cache. Then, from the network the scanner used (or another untrusted vantage point), ask for the same name with recursion turned off:
# Untrusted vantage point, RD bit cleared
dig @192.0.2.53 www.example.org A +norecurse
If the response has status: NOERROR, an ANSWER section and no aa (authoritative answer) flag, the record came from cache and the finding is valid. A restricted BIND server returns status: REFUSED.
Nmap’s dns-cache-snoop script does the same thing against a list of domains. Its default nonrecursive mode sends queries with RD cleared; avoid the timed mode on production, because the Nmap documentation notes it modifies the cache.
nmap -sU -p 53 --script dns-cache-snoop --script-args 'dns-cache-snoop.domains={www.example.org,example.com}' 192.0.2.53
On the server, check the current configuration:
# BIND: print the effective configuration
named-checkconf -p | grep -E "recursion|allow-query-cache|allow-recursion"
# Windows DNS (PowerShell)
Get-DnsServerRecursion
Get-DnsServerRecursionScope
Show-DnsServerCache
How to fix it
BIND 9: internal resolver with a trusted ACL
According to the BIND 9 reference manual, allow-query-cache controls which hosts may issue queries that access the local cache, and allow-recursion controls which hosts may make recursive queries. Each one’s default is derived from the other (and, for allow-recursion, from allow-query), so set both explicitly. Edit /etc/named.conf (RHEL family) or /etc/bind/named.conf.options (Debian and Ubuntu):
acl "trusted" {
localhost;
localnets;
10.0.0.0/8;
192.168.0.0/16;
// add VPN pools, branch sites and IPv6 prefixes you serve
};
options {
recursion yes;
allow-recursion { trusted; };
allow-query-cache { trusted; };
};
Both statements are valid in options and in view blocks, so if you use views, set them per view. Validate and apply:
named-checkconf
rndc reconfig
On a multi-homed server, allow-query-cache-on and allow-recursion-on restrict which local addresses may send cache answers or accept recursive queries, for example only the internal interface. The manual states a client must satisfy both the source and the local-address ACL.
BIND 9: authoritative-only server
If the server only publishes your zones, turn recursion off. The manual notes that recursion no; alone does not stop clients reading data already in the cache, but it also changes the allow-query-cache default to none. Stating it explicitly protects you from an older allow-query-cache { any; }; line elsewhere in the file:
options {
recursion no;
allow-query-cache { none; };
};
The durable design is to separate the roles: public authoritative servers with recursion off, and internal resolvers with an ACL that are not reachable from the Internet.
Windows DNS Server: authoritative-only or unused as a resolver
Windows DNS Server has no direct equivalent of allow-query-cache. If no clients use the server as a resolver, disable recursion. In DNS Manager, right-click the server, choose Properties, open the Advanced tab and select Disable recursion under Server options. In PowerShell:
Set-DnsServerRecursion -Enable $false -PassThru
Clear-DnsServerCache -Force
On builds without the DnsServer module, dnscmd . /Config /NoRecursion 1 does the same. Clearing the cache removes lookups made before the change. Microsoft notes that with recursion disabled you cannot use forwarders on that server.
Windows DNS Server: domain controllers and resolvers clients rely on
Do not disable recursion on a domain controller whose clients use it for Internet names. Restrict who can reach port 53 instead, at the perimeter firewall and on the host. To scope the inbound Windows Firewall rules that open port 53 to your internal ranges:
# Review first
Get-NetFirewallPortFilter | Where-Object -Property LocalPort -EQ 53 | Get-NetFirewallRule | Where-Object Direction -eq Inbound | Format-Table DisplayName, Enabled, Profile
# Then restrict the remote addresses
Get-NetFirewallPortFilter | Where-Object -Property LocalPort -EQ 53 | Get-NetFirewallRule | Where-Object Direction -eq Inbound | Set-NetFirewallRule -RemoteAddress "10.0.0.0/8","192.168.0.0/16"
This only helps if no broader allow rule also admits the traffic, so review the output. On Windows Server 2016 and later, a server that must be authoritative for outside clients and recursive for inside clients can use DNS policy recursion scopes, following Microsoft’s selective recursion control example:
Add-DnsServerRecursionScope -Name "InternalClients" -EnableRecursion $true
Add-DnsServerQueryResolutionPolicy -Name "SplitBrainRecursionPolicy" -Action ALLOW -ApplyOnRecursion -RecursionScope "InternalClients" -ServerInterfaceIP "EQ,10.0.0.39"
Set-DnsServerRecursionScope -Name . -EnableRecursion $false
Microsoft’s example matches the internal interface; client subnets are the documented alternative. Recursion scopes control recursion, and Microsoft does not describe them as a cache access control, so run the seed-then-snoop test from outside afterward. If external non-recursive queries still return cached answers, rely on the firewall restriction.
How to verify the fix and rescan
- Seed a fresh name from an internal client, then repeat the dig +norecurse query from the untrusted vantage point. Expect REFUSED, no answer, or no response.
- Confirm internal clients still resolve Internet names normally.
- Test IPv6 and TCP if the server listens on them, for example dig @2001:db8::53 www.example.org A +norecurse +tcp.
- Rescan with Nessus from the same scanner position that raised plugin 12217. If the scanner sits inside the trusted range, the finding will correctly remain.
What can break and how to roll back
- Missed networks. VPN pools, branch offices, DMZ hosts and IPv6 prefixes left out of the ACL or firewall scope stop resolving.
- Downstream DNS servers. Servers that forward to this one must be inside the trusted range.
- Forwarders on Windows. Disabling recursion also disables forwarding on that server.
- Troubleshooting habits. Admins who inspect the cache with non-recursive queries from outside the ACL will get REFUSED.
# BIND: restore the previous named.conf, then
named-checkconf
rndc reconfig
# Windows: re-enable recursion
Set-DnsServerRecursion -Enable $true
# Windows: undo recursion scopes
Set-DnsServerRecursionScope -Name . -EnableRecursion $true
Remove-DnsServerQueryResolutionPolicy -Name "SplitBrainRecursionPolicy"
# Windows: reopen the firewall rules
Get-NetFirewallPortFilter | Where-Object -Property LocalPort -EQ 53 | Get-NetFirewallRule | Where-Object Direction -eq Inbound | Set-NetFirewallRule -RemoteAddress Any
Common false positive reasons
- The scanner is a trusted client. Any client allowed to use a resolver can read its cache. An internal scanner hitting an internal resolver reports expected behavior; record it as accepted risk.
- BIND’s localnets default. With no explicit ACL, BIND allows cache access from localhost and localnets, so a scanner on the same subnet sees a hit that remote clients would not.
- The answer is not from cache. RPZ, local zones or a DNS filtering appliance may serve local data for the tested name. Check the aa flag.
- The IP is not your DNS server. Firewalls and routers often run a DNS proxy on port 53.
For the wider pattern behind results like these, see our overview of common causes of vulnerability scanner false positives.
FAQ
Is DNS cache snooping a real vulnerability?
It is a real but limited information leak. It reveals which domains were resolved recently, not who resolved them, and it grants no access. Internet-facing exposure matters most.
Does disabling recursion fix Nessus 12217?
On BIND, recursion no; also defaults cache access to none, so yes, unless allow-query-cache is set explicitly. On Windows, disable recursion, clear the cache and retest.
Why does the finding persist after I restricted allow-query-cache?
The scanner is probably inside the trusted ACL or on a directly attached subnet. Rescan from an untrusted network or accept the finding for internal resolvers.
Does DNSSEC stop cache snooping?
No. DNSSEC protects the integrity of answers; it does not hide what is in the cache.
Tracking this finding across many hosts
Plugin 12217 tends to appear on every resolver and domain controller at once, and much of it is accepted risk rather than work. SITEY, a self-hosted vulnerability management platform, imports findings from 16 scanners (Nessus results come in by uploading the exported .nessus file), merges duplicates per scanner, suggests likely false positives with evidence for a human to decide, and can retest individual Nessus findings to confirm closure after a fix.
Sources
- Tenable: Nessus plugin 12217, DNS Server Cache Snooping Remote Information Disclosure
- ISC BIND 9 Administrator Reference Manual: configuration reference
- Microsoft Learn: Set-DnsServerRecursion
- Microsoft Learn: Use DNS Policy for Split-Brain DNS Deployment (selective recursion control)
- Nmap NSE: dns-cache-snoop