06-03: Exercises¶
Question¶
A recursive resolver sends a query out to an authoritative name server:
Shortly after, two responses arrive claiming to answer this query:
Response A:
Transaction ID = 0x4F2A
Source Port = 53 (from the real authoritative server's IP)
Destination Port = 51422
;; ANSWER SECTION:
secure-bank.com. 300 IN A 198.51.100.10
;; AUTHORITY SECTION:
secure-bank.com. 300 IN NS ns1.secure-bank.com.
Response B:
Transaction ID = 0x7C13
Source Port = 53 (spoofed to look like the authoritative server's IP)
Destination Port = 51422
;; ANSWER SECTION:
secure-bank.com. 300 IN A 198.51.100.10
;; AUTHORITY SECTION:
secure-bank.com. 300 IN NS ns1.attacker-controlled.com.
;; ADDITIONAL SECTION:
ns1.attacker-controlled.com. 300 IN A 203.0.113.99
- Which response is the legitimate one, and which is the cache-poisoning attempt? What specifically gives it away?
- Even though the resolver should be able to detect the fake response, explain why a real-world resolver might still be tricked into accepting it.
Solution¶
Step 1: Compare the transaction IDs¶
DNS uses a transaction ID (TXID) — a 16-bit number chosen randomly by the resolver for every outgoing query — specifically so that the resolver can match a response to the query it actually sent, and reject anything that doesn't match.
- The original query used Transaction ID = 0x4F2A.
- Response A: Transaction ID = 0x4F2A → matches.
- Response B: Transaction ID = 0x7C13 → does not match.
This alone is a strong signal that Response B is the forged / cache-poisoning attempt. A correctly-behaving resolver checks the TXID on every incoming response and silently discards any response whose TXID doesn't match an outstanding query. Response B would normally be dropped immediately for this reason.
Step 2: Notice the suspicious Authority section in Response B¶
Beyond the mismatched TXID, Response B contains a second red flag even if the TXID had matched:
;; AUTHORITY SECTION:
secure-bank.com. 300 IN NS ns1.attacker-controlled.com.
;; ADDITIONAL SECTION:
ns1.attacker-controlled.com. 300 IN A 203.0.113.99
- This response doesn't just supply an A record for
secure-bank.com— it also tries to sneak in a claim thatsecure-bank.com's authoritative name server is nowns1.attacker-controlled.com, along with a "helpful" glue A record pointing that name at203.0.113.99(an attacker-controlled IP). - This is a classic cache-poisoning / Kaminsky-style injection technique: by riding along extra NS and glue records in the Authority/Additional sections of a response, an attacker tries to get the resolver to cache the idea that all future queries for
secure-bank.com(not just this one A record) should be sent to the attacker's fake name server. If the resolver blindly trusts and caches this, the attacker gains standing control over the domain in that resolver's cache — a much bigger win than poisoning a single A record. - A response that suddenly reassigns authority for a well-established domain to an unfamiliar, out-of-bailiwick name server is inherently suspicious and is exactly the pattern a resolver's bailiwick-checking logic should reject.
Step 3: Why might a resolver still be tricked, despite these defenses?¶
Even though transaction ID checking and bailiwick checking exist, real resolvers have historically still been vulnerable for practical reasons:
- The transaction ID space is only 16 bits (65,536 values). An attacker who can send a flood of guessed responses very quickly (e.g., thousands per second) has a realistic chance of guessing the correct TXID before the real authoritative response arrives — especially if they can also predict or narrow down the query timing (e.g., by first triggering the resolver to look up the domain).
- Source port used to be predictable/fixed. Historically, many resolvers always sent DNS queries from the same fixed source port (port 53). This cut the attacker's search space down to just the 16-bit TXID, since the destination port for the forged response was already known. The Kaminsky attack (2008) demonstrated exactly this weakness. The fix — source port randomization — combines with TXID randomization to make the effective "guess space" much larger (16 bits of TXID x ~16 bits of port ≈ 32 bits), making brute-force spoofing far less practical.
- Timing race condition. DNS over UDP has no handshake — a resolver simply accepts the first response that matches the expected TXID (and, on stricter implementations, the expected source IP/port), no matter who really sent it. If an attacker can spoof a response that lands in the resolver's queue before the legitimate authoritative server's real answer, and it happens to guess the TXID/port correctly, the resolver has no further way to tell it's fake from the packet alone — DNS responses over plain UDP are not cryptographically signed by default.
- No source authentication in classic DNS. Without DNSSEC, there's no cryptographic signature tying a response to the genuine authoritative server, so a resolver's only defenses are the TXID, the source port, and matching the query name/type/class — all of which can, with enough attempts or a favorable position on the network path, be spoofed or brute-forced by a motivated attacker.
This is precisely why modern deployments recommend DNSSEC (which adds cryptographic signatures resolvers can verify) on top of TXID and source-port randomization — randomization only raises the cost of the attack, it doesn't make forgery cryptographically impossible.
Final Answer¶
- Response A is legitimate: its Transaction ID (0x4F2A) matches the original query.
- Response B is the cache-poisoning attempt: its Transaction ID (0x7C13) does not match, and it additionally tries to inject a forged NS + glue A record pointing
secure-bank.com's authority at an attacker-controlled server — a classic cache-poisoning injection technique. - A resolver can still be fooled in practice because: (a) the 16-bit TXID space can be brute-forced with enough forged packets sent quickly, (b) historically-fixed/predictable source ports made guessing easier (mitigated by source port randomization), (c) plain UDP DNS has no signature verification, so the resolver just accepts the first response that matches TXID/port, and (d) without DNSSEC there is no cryptographic proof of authenticity — only randomization raising the guessing difficulty.