Send, receive, and shield emails with PostScale. One API, EU-hosted. PostScale

    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.34

    The 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:

    LayerExampleTTL Behavior
    Stub resolverYour OS DNS cacheCaches per machine
    Recursive resolver8.8.8.8, 1.1.1.1, ISP DNSCaches for all users of that resolver
    ForwarderCorporate DNS forwarderCaches 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:

    1. 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.
    2. Before the legitimate response arrives, the attacker floods the resolver with forged UDP responses, each claiming to be the answer from the authoritative server.
    3. Each DNS response contains a 16-bit Transaction ID (TXID) that must match the query. The attacker has to guess this value.
    4. 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-|
       |                            |     (Ignoredalready 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:

    1. Query the resolver for random001.example.com
    2. Flood forged responses claiming to be from the example.com nameserver
    3. The forged response includes an Authority section that delegates example.com to the attacker's nameserver
    4. If the TXID guess fails, immediately try random002.example.com
    5. 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.66

    Once 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:

    1. The response came from the legitimate authoritative server
    2. The data has not been modified in transit
    3. 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 signature

    With 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:

    1. The A record answer comes with an RRSIG (signature) record
    2. The resolver fetches the DNSKEY from the zone's authoritative server
    3. It verifies the DNSKEY is authenticated by a DS record in the parent zone
    4. 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 answer

    Query 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 poisoned

    Check 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 validation

    If 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:

    VulnerabilityRiskFix
    Fixed source portAttacker only guesses 16-bit TXIDEnable source port randomization
    No DNSSEC validationForged responses accepted blindlyEnable DNSSEC validation
    Open resolverAnyone can trigger queriesRestrict to authorized clients
    Outdated softwareMissing security patchesKeep resolver software updated
    No 0x20 encodingLess entropy in queriesEnable 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 answer

    Protecting 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:

    1. Enable DNSSEC validation — this is the most important single step
    2. Verify source port randomization is active
    3. Restrict recursion to authorized clients only — do not run an open resolver
    4. Enable 0x20 encoding if your software supports it (Unbound does by default)
    5. Keep software updated — resolver bugs have been exploited for poisoning
    6. Monitor for anomalies — unexpected spikes in NXDOMAIN or SERVFAIL responses can indicate a poisoning attempt
    7. Consider DNS over TLS for forwarding — encrypting the link between your forwarder and upstream resolver prevents on-path attackers from injecting responses

    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