How did the Kaminsky technique make off-path DNS cache poisoning practical without waiting for TTLs, and what did recursive resolvers change in response?
answer
- race for names nobody cached
- authority section carries the payload
- one race per query, not per TTL
- the source port as a second ID
- letter case as extra bits
basics
~20 sThe Kaminsky technique queries random uncached names under a target zone, so each query opens a fresh race, and forged replies carry NS records capturing the whole zone. Resolvers answered with unpredictable source ports (RFC 5452) and 0x20 case randomisation.
solid answer
~50 sClassically an off-path forger raced the genuine answer for one name; after a loss the real record sat in cache for its TTL, so a long TTL rationed attempts (RFC 5452 section 7). The Kaminsky technique removed that brake: make the resolver look up `a1.example.com`, `a2.example.com` and so on - names nobody has cached - so each query is a new race. Each forged reply answers the random name and adds `NS` records for `example.com` pointing at the attacker's server, data a resolver accepts because it comes from a supposed authority for a parent of the queried name. One win captures the zone. Against a fixed source port, RFC 5452 section 8.1 puts a 7000 packets/s attacker at 50% within 7 seconds. The response was RFC 5452's MUST for unpredictable source ports and IDs - about 116 hours with 64000 ports - plus 0x20 case randomisation, an Internet-Draft; DNSSEC validation is the cryptographic fix.
code
dns · 8 lines;; forged response to the resolver's query for a17.example.com IN A
;; ID guessed; source port guessed
;; ANSWER SECTION:
a17.example.com. 300 IN A 192.0.2.66
;; AUTHORITY SECTION:
example.com. 86400 IN NS ns.attacker.example.net.
;; ADDITIONAL SECTION:
ns.attacker.example.net. 86400 IN A 198.51.100.53go deeper
Remember that the attack floods a resolver with forged answers for random names, and that random source ports plus random query IDs are what make guessing hard.
Explain why querying uncached names removes the TTL wait, and why the forged NS record in the authority section is the real payload.
Quantify the defence with RFC 5452's numbers, name what undoes it such as port-rewriting devices, and state that only DNSSEC validation proves origin.
Decide where to invest: resolver placement that preserves port entropy, DNSSEC validation, and whether encrypting resolver-to-authoritative traffic is worth its operational cost.
## The race an off-path forger must win A recursive resolver that sends a query over UDP accepts the first datagram that matches it. RFC 5452 section 9.1 lists what must match: both addresses, the destination port against the query's source port, the **query ID**, the query name, and the class and type. An **off-path** attacker - one who cannot see the query - knows the name it made the resolver ask and the authoritative servers' addresses; it must guess the ID and the source port and deliver its guess in the **window of opportunity** before the genuine answer arrives, which RFC 5452 puts at often around 0.1 s. ## Why the TTL used to be the brake In the classic attack the forger races for the very record it wants to plant, say `www.example.com`. If the genuine answer wins, the resolver caches it and sends no new query until its **TTL** expires. RFC 5452 section 7 models this: attempts arrive once per TTL, so a short TTL makes spoofing far more viable. Its worked example against a fixed source port: at 7000 forged packets per second, a record with a 3600-second TTL has a 10% chance of being spoofed in the first 24 hours and 50% after a week. ## The Kaminsky construction The technique, named after the researcher who publicised it, removes the wait: 1. The attacker makes the resolver query names that cannot be cached - `a1.example.com`, `a2.example.com`, and so on - directly if the resolver is open, or indirectly, for instance by making a mail server look them up. 2. Each query opens a **new window**, so there is no TTL to wait out; RFC 5452 section 8.1 says such repeated-query techniques reduce the effective TTL to 0. 3. Into each window the attacker fires forged responses claiming to come from an `example.com` authoritative server, guessing the ID. 4. Each forgery answers the random name and carries, in its **authority section**, `NS` records saying `example.com` is served by `ns.attacker.example.net`, with an address for it. 5. When one guess matches, the resolver stores those records, and every later lookup under `example.com` goes to the attacker. The payload is not the answer but the delegation that rides along with it. ## Why the in-domain check did not stop it RFC 5452 section 6 tells resolvers to accept data only if the originator is authoritative for the query name or a parent of it - the idea older texts call a **bailiwick** check, a term RFC 9499 now calls historic. Here the forged `NS` data is for `example.com`, the parent of the queried name, and it claims to come from `example.com`'s own server. The check passes. RFC 2181 section 5.4.1 ranks authority-section data from an authoritative answer above glue, which is why such data could displace what the cache held. ## The entropy stack that answered it | Layer | Space it adds | Source | Limits | |---|---|---|---| | Query ID | 16 bits, 0-65535 | RFC 1035 header; RFC 5452 requires the full range, unpredictably | Too small alone against fast retries | | Source port | Up to about 64000 ports (ports below 1024 are not always available) | RFC 5452 section 9.2 MUST, from 53 or 1024 and above | A device in front that rewrites ports predictably undoes it | | Source address | Multiple resolver addresses, used unpredictably | RFC 5452 SHOULD | Needs several addresses | | 0x20 letter case | About one bit per letter in the name | An Internet-Draft technique, never an RFC | Short names and digits add little; servers must echo the question's case | The arithmetic from RFC 5452 section 8.1 shows the effect: with repeated queries at 7000 packets per second, one source port gives the attacker a 50% chance within 7 seconds; 64000 ports push the same 50% to around 116 hours. **0x20 randomisation** exploits two rules in RFC 1034: names compare case-insensitively, yet a server that receives a name should preserve its case. A resolver sends `wWw.eXaMpLe.cOm`, the genuine server echoes that question exactly, and a forger who never saw the query must also guess the case pattern. ## What remains after randomisation - Randomisation raises the **cost** of guessing; it proves nothing about where data came from. - The cryptographic fix is **DNSSEC validation**, where a forged `NS` set or address simply fails to verify for a signed zone. - Restricting which authority and additional data a resolver caches, and never promoting it into answers, narrows what a winning forgery can plant, as RFC 2181 section 5.4.1 recommends. - Encrypting the resolver-to-authoritative hop, which RFC 9250 defines for DoQ, replaces the blind-guessing race on that hop with a connection an off-path forger cannot inject into.
- Why does a long TTL on www.example.com not protect it against the Kaminsky technique?The attacker never races for `www.example.com`. It races for random uncached names under the zone, each of which triggers a fresh query, and plants delegation data for the zone itself. RFC 5452 section 8.1 notes such repeated-query techniques reduce the effective TTL to 0, so the target record's TTL no longer rations attempts.
- A resolver randomises its source ports, but sits behind a device that rewrites them to a sequential range. What happens to the protection?Most of it is lost. The authoritative server replies to the rewritten port, so a forger only needs to predict what the device will pick next. RFC 5452 section 9.2.1 warns that a resolver with few upstream-facing endpoints is effectively using constants. The rewriting device must itself randomise, or the resolver must sit where ports survive.
saying these in an interview costs you the question
- Kaminsky poisoning only works when the target record's TTL has just expired.
- Bailiwick checks block forged NS records sent for the parent zone.
- Source-port randomisation makes off-path poisoning cryptographically impossible.
- 0x20 case randomisation is required by RFC 5452.
- Randomising the query ID alone gives 32 bits of protection.