DNS Cache Poisoning Explained — How It Works and How to Prevent It
Learn how DNS cache poisoning works, why the Kaminsky attack was so devastating, and how DNSSEC, source port randomization, and other defenses protect against DNS spoofing.
DNS cache poisoning is one of the most dangerous attacks against the Domain Name System. By injecting forged records into a resolver's cache, an attacker can silently redirect thousands of users to malicious servers without compromising a single endpoint. Understanding how cache poisoning works — and how modern defenses stop it — is essential for anyone managing DNS infrastructure.
What You'll Learn
- How DNS caching works and why it creates an opportunity for poisoning attacks
- The mechanics of classic cache poisoning and the Kaminsky attack variant
- How DNSSEC provides cryptographic proof that DNS responses are authentic
- How to detect cache poisoning and verify your resolver is returning correct answers
How DNS Caching Works
Before understanding cache poisoning, you need to understand how DNS resolution and caching operate.
When a recursive resolver receives a query for a domain it hasn't seen recently, it walks the DNS hierarchy: root servers, then TLD servers, then the authoritative nameserver for the domain. Once it gets an answer, it stores (caches) that response for the duration specified by the record's TTL (Time to Live).
# Query a resolver and observe the TTL countdown
dig example.com A @8.8.8.8
;; ANSWER SECTION:
example.com. 86400 IN A 93.184.216.34
# Query again a few seconds later — the TTL has decreased
dig example.com A @8.8.8.8
;; ANSWER SECTION:
example.com. 86372 IN A 93.184.216.34The TTL counts down on the resolver side. Until it reaches zero, the resolver serves the cached answer without contacting the authoritative server. This is efficient and reduces latency, but it also means that any forged record that makes it into the cache will be served to every user of that resolver until the TTL expires.
The Caching Chain
Multiple layers of caching exist:
| Layer | Example | TTL Behavior |
|---|---|---|
| Stub resolver | Your OS DNS cache | Caches per machine |
| Recursive resolver | 8.8.8.8, 1.1.1.1, ISP DNS | Caches for all users of that resolver |
| Forwarder | Corporate DNS forwarder | Caches for all users on the network |
A poisoned entry at the recursive resolver level affects the largest number of users, which is why attackers target resolvers rather than individual machines.
The Classic Cache Poisoning Attack
The original cache poisoning attack exploits a race condition in the DNS protocol. Here is how it works:
- The attacker sends a query to a recursive resolver for a domain like
www.example.com, forcing the resolver to look up the answer from the authoritative server. - Before the legitimate response arrives, the attacker floods the resolver with forged UDP responses, each claiming to be the answer from the authoritative server.
- Each DNS response contains a 16-bit Transaction ID (TXID) that must match the query. The attacker has to guess this value.
- If a forged response arrives with the correct TXID before the real response, the resolver accepts and caches the forged A record — pointing the domain to the attacker's IP.
Attacker Resolver Authoritative NS
| | |
|--- Query: www.example.com->| |
| |--- Query (TXID=0x4a2f) --->|
|--- Forged reply TXID=0x0001 ->| |
|--- Forged reply TXID=0x0002 ->| |
|--- Forged reply TXID=0x0003 ->| |
| ... | |
|--- Forged reply TXID=0x4a2f ->| (MATCH! Cached!) |
| |<--- Real reply TXID=0x4a2f-|
| | (Ignored — already answered)Why Classic Poisoning Was Hard
With a 16-bit TXID, there are 65,536 possible values. The attacker gets one attempt per query — if the real answer arrives first, the window closes and the attacker must wait for the cached entry to expire before trying again. This could take hours or days depending on the TTL.
The birthday paradox does help attackers somewhat: by sending queries for many different names simultaneously, they get multiple "lottery tickets." But the attack was still impractical against well-configured resolvers with reasonable TTLs.
The Kaminsky Attack (2008)
In 2008, security researcher Dan Kaminsky revealed a devastating improvement to cache poisoning that made it practical to poison any domain within seconds.
How the Kaminsky Attack Works
The key insight was eliminating the TTL wait. Instead of querying for www.example.com repeatedly, the attacker queries for random, non-existent subdomains:
- Query the resolver for
random001.example.com - Flood forged responses claiming to be from the
example.comnameserver - The forged response includes an Authority section that delegates
example.comto the attacker's nameserver - If the TXID guess fails, immediately try
random002.example.com - Repeat — there is no TTL wait because each subdomain is unique
# The attacker's forged response includes a glue record:
# ;; AUTHORITY SECTION:
# example.com. 172800 IN NS ns1.evil.com.
#
# ;; ADDITIONAL SECTION:
# ns1.evil.com. 172800 IN A 203.0.113.66Once the resolver accepts the forged authority record, the attacker controls all DNS resolution for example.com — not just a single subdomain. Every subsequent query for any record under example.com is answered by the attacker's server.
Why It Was Devastating
The Kaminsky attack could poison a major domain's DNS in under 10 seconds on many resolvers. With 65,536 possible TXIDs and the ability to send thousands of forged packets per second, the probability of a match reaches near-certainty very quickly.
The attack was so severe that a coordinated multi-vendor patch was released simultaneously in July 2008, before Kaminsky publicly disclosed the technical details. It remains one of the most significant DNS vulnerabilities ever discovered.
The Birthday Attack on Transaction IDs
The birthday paradox applies to DNS poisoning in an important way. If the attacker can cause the resolver to send multiple outstanding queries, the probability of matching at least one TXID increases dramatically. With n outstanding queries and k forged responses, the chance of at least one collision follows birthday-problem mathematics:
- 300 forged packets against 1 query: ~0.46% chance
- 300 forged packets against 50 queries: ~20% chance
- 700 forged packets against 50 queries: ~41% chance
This is why the Kaminsky attack, which generates unlimited fresh queries, was so much more effective than the classic approach.
Modern Defenses Against Cache Poisoning
The DNS community has deployed multiple layers of defense since 2008.
Source Port Randomization
Before the Kaminsky disclosure, many resolvers used a fixed or predictable source UDP port for outgoing queries. This meant the attacker only needed to guess the 16-bit TXID.
After the patch, resolvers randomize the source port, adding roughly 16 bits of additional entropy. Combined with the TXID, an attacker must now guess from approximately 2^32 (over 4 billion) combinations — making brute-force poisoning impractical.
# Check if your resolver uses randomized source ports
# Each query should show a different source port
dig +short porttest.dns-oarc.net TXT @your-resolver-ip
# Expected output for a well-configured resolver:
# "your-resolver-ip is GOOD: 26 of 26 ports randomized"0x20 Encoding (DNS Cookies Lite)
Some resolvers implement 0x20 bit encoding, which randomizes the capitalization of the query name. Since DNS is case-insensitive but preserves case in responses, the resolver can verify that the response matches the exact capitalization it used:
- Query:
wWw.ExAmPlE.cOm - Valid response must echo:
wWw.ExAmPlE.cOm - Attacker must guess the exact capitalization pattern
This adds additional bits of entropy that the attacker cannot predict. For a 15-character domain name, 0x20 encoding adds roughly 15 bits of entropy.
DNSSEC — The Definitive Solution
DNSSEC is the only defense that makes cache poisoning fundamentally impossible rather than merely impractical. DNSSEC adds cryptographic signatures to DNS responses, allowing validating resolvers to verify that:
- The response came from the legitimate authoritative server
- The data has not been modified in transit
- The chain of trust leads back to a known root key
# Query with DNSSEC validation enabled
dig example.com A +dnssec
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2
;; ANSWER SECTION:
example.com. 86400 IN A 93.184.216.34
example.com. 86400 IN RRSIG A 13 2 86400 ...
# The 'ad' flag means the resolver validated the DNSSEC signatures
# The RRSIG record contains the cryptographic signatureWith DNSSEC, even if an attacker guesses the TXID and source port, the forged response will not have a valid cryptographic signature. A validating resolver will reject it.
DNSSEC protects the data itself, not the transport. Even if an attacker intercepts or races a response, they cannot forge a valid signature without the zone's private signing key.
How DNSSEC Validation Works
When a resolver receives a DNSSEC-signed response, it verifies the signature chain:
- The A record answer comes with an RRSIG (signature) record
- The resolver fetches the DNSKEY from the zone's authoritative server
- It verifies the DNSKEY is authenticated by a DS record in the parent zone
- This chain continues up to the DNS root, which the resolver trusts via a built-in root key
# View the DNSSEC chain for a domain
dig example.com DNSKEY +dnssec +short
dig example.com DS +dnssec +short
# Verify DNSSEC validation is working on your resolver
dig sigfail.verteiltesysteme.net A @8.8.8.8
# Should return SERVFAIL (invalid signature, correctly rejected)
dig sigok.verteiltesysteme.net A @8.8.8.8
# Should return an A record (valid signature, accepted)For a deeper comparison of DNSSEC with transport-layer encryption, see DNSSEC vs DNS over HTTPS.
Detecting Cache Poisoning
If you suspect your resolver has been poisoned, you can verify by comparing answers from multiple independent sources.
Compare Answers Across Resolvers
# Query multiple public resolvers for the same domain
dig example.com A @8.8.8.8 +short # Google DNS
dig example.com A @1.1.1.1 +short # Cloudflare DNS
dig example.com A @9.9.9.9 +short # Quad9
dig example.com A @208.67.222.222 +short # OpenDNS
# If one resolver returns a different IP, it may be poisoned
# All should return the same authoritative answerQuery the Authoritative Server Directly
# Find the authoritative nameservers
dig example.com NS +short
# Query the authoritative server directly (bypasses resolver cache)
dig example.com A @ns1.example.com +short
# Compare with your resolver's answer
dig example.com A @your-resolver +short
# If these differ, your resolver's cache may be poisonedCheck DNSSEC Validation
# If the domain supports DNSSEC, check for the 'ad' (Authenticated Data) flag
dig example.com A +dnssec @8.8.8.8
# Look for 'ad' in the flags line:
# ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2
# The 'ad' flag confirms the answer passed DNSSEC validationIf DNSSEC validation is enabled on your resolver and the domain is signed, a poisoned answer will fail validation and return SERVFAIL instead of being silently accepted.
Signs of Poisoning
Watch for these indicators:
- DNS answers that differ between resolvers for the same query
- Unexpected IP addresses for well-known domains
- DNSSEC validation failures (SERVFAIL) on domains that previously resolved
- Users reporting certificate warnings when visiting HTTPS sites (the poisoned IP serves a different certificate)
- Sudden changes in DNS TTL values you did not configure
Real-World Cache Poisoning Incidents
The 2008 Coordinated Disclosure
When Dan Kaminsky discovered his attack variant, he coordinated with every major DNS vendor (Microsoft, BIND, Unbound, and others) to release patches simultaneously. Despite a requested embargo period, details leaked early, leading to a race between defenders patching and attackers attempting exploitation. Multiple ISP resolvers were confirmed poisoned in the weeks following disclosure.
Brazilian Banking Attack (2009)
Attackers poisoned a major Brazilian ISP's DNS resolver, redirecting one of Brazil's largest banks to a replica site. Customers who logged in had their credentials stolen. The attack lasted several hours before detection and affected an estimated 1% of the bank's customer base.
DNS Changer Malware (2007-2011)
The DNSChanger trojan modified infected computers' DNS settings to point to attacker-controlled resolvers. These rogue resolvers served poisoned answers for advertising fraud and phishing. At its peak, DNSChanger infected over 4 million machines across 100+ countries. The FBI eventually seized the rogue DNS servers in Operation Ghost Click.
Common Resolver Vulnerabilities
Several configuration issues make resolvers more susceptible to poisoning:
| Vulnerability | Risk | Fix |
|---|---|---|
| Fixed source port | Attacker only guesses 16-bit TXID | Enable source port randomization |
| No DNSSEC validation | Forged responses accepted blindly | Enable DNSSEC validation |
| Open resolver | Anyone can trigger queries | Restrict to authorized clients |
| Outdated software | Missing security patches | Keep resolver software updated |
| No 0x20 encoding | Less entropy in queries | Enable if resolver supports it |
# Test if a resolver validates DNSSEC
dig @your-resolver dnssec-failed.org A
# A validating resolver returns SERVFAIL
# A non-validating resolver returns an answerProtecting Your Zones with DNScale
As an authoritative DNS provider, DNScale helps protect your domains against cache poisoning in several ways:
- DNSSEC signing — sign your zones so that validating resolvers can verify your records are authentic and reject forged responses
- Short, sensible TTLs — configurable TTL values so poisoned entries expire quickly
- Anycast distribution — responses come from the nearest anycast node, reducing the window for an attacker to race a forged response
- NSEC/NSEC3 records — authenticated denial of existence prevents attackers from poisoning negative responses
If you manage DNS for critical infrastructure, enabling DNSSEC on your zones is the single most effective step you can take against cache poisoning. See our DNS security best practices guide for a complete checklist.
Best Practices for Resolver Operators
If you operate a recursive resolver (even a local forwarding resolver), follow these hardening steps:
- Enable DNSSEC validation — this is the most important single step
- Verify source port randomization is active
- Restrict recursion to authorized clients only — do not run an open resolver
- Enable 0x20 encoding if your software supports it (Unbound does by default)
- Keep software updated — resolver bugs have been exploited for poisoning
- Monitor for anomalies — unexpected spikes in NXDOMAIN or SERVFAIL responses can indicate a poisoning attempt
- Consider DNS over TLS for forwarding — encrypting the link between your forwarder and upstream resolver prevents on-path attackers from injecting responses
Related Topics
- What Is DNS — how DNS resolution works end to end
- DNS Record Types — the record types targeted by poisoning attacks
- DNSSEC and DNS Security — the definitive defense against cache poisoning
- DNSSEC vs DNS over HTTPS — understanding data integrity vs transport encryption
- DNS Attacks and Threats — the full landscape of DNS-based attacks
- What Is a DDoS Attack — another major DNS threat vector
- DNS NS Records — how delegation works and why authority records matter in poisoning
- DNS A Records — the primary record type targeted by poisoning
- DNS Security Best Practices — a complete security hardening guide
Conclusion
DNS cache poisoning exploits the trust that resolvers place in unsigned DNS responses. The classic attack was difficult but possible; the Kaminsky variant made it trivially exploitable. Modern defenses — source port randomization, 0x20 encoding, and most importantly DNSSEC — have made poisoning far more difficult, but only DNSSEC provides a cryptographic guarantee that the answer is authentic. If you manage DNS zones, sign them with DNSSEC. If you operate resolvers, enable DNSSEC validation. These two steps together close the door on cache poisoning for good.
Ready to manage your DNS with confidence?
DNScale provides anycast DNS hosting with a global network, real-time analytics, and an easy-to-use API.
Start free