What Is DNS Cache Poisoning? Kaminsky Attack Explained
DNS cache poisoning is an attack that injects fraudulent records into a resolver's cache, silently redirecting users to attacker-controlled servers while the address bar shows the legitimate domain name. It exploits the fundamental design of DNS: resolvers cache answers to avoid repeating expensive lookups, and the original DNS protocol had no mechanism to verify that an answer actually came from the authoritative name server.
How Resolver Caching Works
When your browser loads example.com, your operating system asks a recursive resolver — typically one operated by your ISP, your organization, or a public service like Quad9 (9.9.9.9) or Google (8.8.8.8) — to find the answer. The resolver walks the DNS hierarchy: it contacts a root server, is referred to a TLD server for .com, then contacts the authoritative server for example.com, and finally returns the A or AAAA record to your browser.
That final answer is cached for its TTL — time to live — specified in the record itself. During that window, any subsequent query for the same name returns the cached answer instantly without repeating the delegation chain. For the resolver operator this is essential: a large resolver handles millions of queries per second, and re-walking the tree for every query would collapse under load.
The attack surface is precisely this cache. If an attacker can get the resolver to store a fraudulent record, every client that resolver serves will receive the poisoned answer until the TTL expires.
Classic Cache Poisoning: Racing the Real Answer
DNS uses UDP by default. A resolver sends a query packet and waits for a response. The response is accepted if it arrives on the same port the query was sent from, matches the destination IP of the authoritative server, and carries the same 16-bit query ID that was embedded in the original query.
Classic poisoning works by flooding the resolver with forged responses while a real lookup is in flight:
- The attacker tricks or waits for the resolver to query for a name (e.g., by causing a cache miss for
bank.com) - While the real query is traveling to the authoritative server, the attacker sends thousands of forged UDP responses, each guessing a different query ID
- The query ID space is only 16 bits — 65,536 possibilities. If the attacker can flood enough forged packets before the real answer arrives, the probability of a hit is meaningful
- If a forged response lands first with the correct query ID, the resolver accepts it and caches the fraudulent record
Early implementations accepted almost any response that matched the query ID, ignoring whether the source IP was actually the authoritative server. With source IP checking added, the attacker still only needs to guess the query ID, but must also spoof the source IP — achievable without BGP-level control of the network, just through IP spoofing.
The Kaminsky Attack (2008)
Dan Kaminsky disclosed a fundamental amplification of classical poisoning in 2008 that made the attack practical against any resolver on the internet. The key insight was about cache longevity: classic poisoning could be defeated by simply waiting — once the TTL expired, the cache was clean again. Kaminsky's technique let an attacker retry indefinitely, turning a probabilistic race into a near-certain outcome.
The technique exploits two properties of DNS:
- Random subdomains force fresh lookups. Queries for
a1b2.bank.com,x9y8.bank.com, andq3r4.bank.comwill all miss the cache because each is a unique name that has never been queried before. Each cache miss causes the resolver to send a new query to the authoritative server — giving the attacker a new race to win. - In-bailiwick additional records. A DNS response is allowed to include additional records in the "additional" section when they are in-bailiwick — within the zone being answered for. If an attacker wins the race for
a1b2.bank.com, they can include a forged NS record claimingbank.com's nameserver isns.attacker.com, and a forged glue A record sayingns.attacker.comhas the attacker's IP. A buggy resolver would cache this, handing the attacker control of all future lookups for the entirebank.comzone.
The attack loop is:
- Send a query for a random subdomain of the target zone (e.g.,
rand1234.bank.com) to the resolver - Immediately flood forged responses guessing the 16-bit query ID
- Each forged response carries a fabricated NS record redirecting
bank.comto the attacker's nameserver - If the guess fails, repeat from step 1 with a new random subdomain — no waiting for TTL
- Once a forged response is accepted, the resolver now asks the attacker's server for all future
bank.comlookups
With a 16-bit query ID and the ability to send ~1,000 forged packets per attempt, an attacker could expect success within roughly 65,536 / 1,000 = ~66 attempts — achievable in seconds over a high-bandwidth link.
Bailiwick Rules: Containing What Can Be Cached
Before Kaminsky's disclosure, DNS implementations varied in how strictly they enforced bailiwick rules — the principle that a DNS response may only add records to the cache for names that fall within the zone being answered. This is codified in RFC 2181 and earlier guidance, but enforcement was inconsistent.
A response to a query for rand1234.bank.com is in-bailiwick for the bank.com zone. An NS record claiming bank.com NS ns1.attacker.com is also in-bailiwick (it's about the bank.com zone). But a glue record ns1.google.com A 203.0.113.1 in the additional section of a bank.com response is out-of-bailiwick and must be discarded.
The Kaminsky attack specifically exploited in-bailiwick authority records — the NS record redirect was for the target zone itself, which is a legitimate thing to include. Strict bailiwick enforcement alone does not stop this. What it prevents is cross-zone poisoning, where a response for one zone tries to inject records for an entirely different zone. Post-Kaminsky, all major resolvers enforce bailiwick strictly, but it is not a complete defense.
Mitigations Deployed After Kaminsky
Kaminsky coordinated a multi-vendor patch release in July 2008. The primary countermeasure was source port randomization: instead of sending all DNS queries from a fixed port (historically UDP/53), resolvers now pick a random ephemeral source port for each outgoing query. The attacker must now guess both the 16-bit query ID and the 16-bit source port — roughly 232 combinations, making flooding attacks impractical with reasonable bandwidth.
| Mitigation | What it adds | Entropy bits |
|---|---|---|
| None (original DNS) | — | 16 (query ID only) |
| Source port randomization | Random source port per query | ~32 (ID + ~16-bit port) |
| 0x20 case randomization | Random mixed-case query name | +N bits (N = chars in name) |
| DNS Cookies (RFC 7873) | Server-verified 64-bit client cookie | +64 |
| DNSSEC | Cryptographic signatures on records | full public-key security |
Bailiwick checking was tightened at the same time: a response to a query for rand1234.bank.com is only allowed to include records within the bank.com zone. A forged additional record claiming authority over google.com in a bank.com response must be discarded. All major resolvers enforce this today.
0x20 encoding (case randomization) is a technique where the resolver sends queries with the name in randomly mixed case — e.g., BaNk.CoM — and the authoritative server is expected to echo the case back unchanged. A forged response that doesn't match the exact case pattern is rejected. Since an attacker observing only the query volume cannot easily determine the case sequence, this adds meaningful entropy. It is deployed by several major resolvers but not universally, because some authoritative servers incorrectly normalize case.
DNS Cookies (RFC 7873) work differently: the client sends a 64-bit cookie derived from its IP and a secret, and the server returns its own server cookie. On subsequent queries to the same server, the client includes the last-known server cookie; the server validates it. A spoofed response from a forged source cannot include a valid server cookie. This requires both sides to support the EDNS option and is incrementally deployable.
DNSSEC: The Cryptographic Fix
All of the above measures raise the cost of poisoning but do not eliminate the vulnerability. DNSSEC provides the only complete solution. Zone operators sign their records with a private key; resolvers that perform DNSSEC validation check the signature against the public key published in the parent zone. A forged A record without a valid signature is rejected regardless of how the attacker guessed the query ID.
DNSSEC adoption is widespread among TLDs but uneven at the second-level zone level. As of 2025, roughly 90% of TLDs are DNSSEC-signed, but fewer than 30% of second-level domains under .com have DNSSEC records. Recursive resolvers that enforce DNSSEC validation (including most public resolvers) will refuse to serve unsigned zones only if the parent explicitly marks them as "signed but broken" — the default for unsigned zones is to serve unsigned answers.
SAD DNS (2020): A Side-Channel Revival
In 2020, researchers disclosed SAD DNS (Side-channel AttackeD DNS), a technique that partially defeats source port randomization by exploiting the behavior of ICMP port-unreachable messages. When a resolver sends a DNS query to a wrong port, the OS kernel may send back an ICMP "port unreachable" packet. By probing different ports and observing whether ICMP responses arrive, an off-path attacker can infer the source port the resolver is using for a live query, reducing the entropy from ~32 bits back toward ~16 bits.
The attack requires the ability to send spoofed packets and observe ICMP responses, making it harder to execute than pure flooding but still meaningful against some resolver configurations. Mitigations include ICMP rate limiting (already common on many kernels), filtering ICMP at the resolver, and preferring TCP or DNS-over-TLS for upstream queries — connections that are not susceptible to this class of attack.
DNS over TCP and Encrypted Transports
Standard DNS uses UDP for most queries, with TCP used as a fallback for responses that exceed 512 bytes (or the negotiated EDNS buffer size). TCP-based DNS queries are immune to the classic UDP spoofing attack because TCP requires a full three-way handshake: an off-path attacker cannot complete the handshake or inject forged responses into an established TCP session without compromising a network device on the path.
DNS over TLS (DoT, RFC 7858) and DNS over HTTPS (DoH, RFC 8484) provide both confidentiality and integrity: TLS authentication ensures the resolver is talking to the real upstream server, and the encrypted channel prevents injection of forged responses by any on-path observer. For stub resolvers sending queries upstream, these protocols eliminate the poisoning risk entirely — though they shift trust to the encrypted resolver operator rather than the network path.
For recursive resolvers querying authoritative servers, adoption of DoT for upstream queries (sometimes called "DoT for upstream" or "stub-to-resolver encryption") is less universal because it requires authoritative operators to support TLS, and many still do not. The path most vulnerable to poisoning in modern deployments is therefore the resolver-to-authoritative leg, where plain UDP is still the norm.
What Attackers Do With a Poisoned Cache
Cache poisoning is a means to an end. Common objectives:
- Credential theft: redirect
bank.comto a phishing page that serves a cloned login form over HTTP or a fraudulently obtained TLS certificate - Mail interception: poison the MX record for a domain so that inbound email is delivered to an attacker-controlled server — effective for password reset interception and business email compromise
- Software update hijacking: redirect update endpoints to serve malicious payloads
- Advertising fraud and surveillance: redirect any domain to attacker infrastructure for traffic analysis or ad injection
Unlike BGP-level attacks that affect routing globally, DNS poisoning is scoped to the users of the affected resolver — a single ISP resolver compromise can affect millions of customers while remaining invisible to the rest of the internet.
Detection
Operators can detect poisoning by querying their authoritative name servers directly (bypassing the recursive resolver) and comparing answers to what the resolver returns. Significant differences indicate cache tampering. DNSSEC validation failures are a reliable signal when deployed. Monitoring DNS response times is also useful: poisoned records served from an attacker's nearby server may have anomalously low latency compared to geographically distant legitimate authoritative servers.
For defenders operating resolvers, logging all outgoing queries and incoming responses, along with their source IPs, provides an audit trail for forensic analysis after suspected poisoning events.