In the summer of 2008, sixteen people sat in a room on Microsoft’s campus in Redmond and quietly agreed on the date they would patch the internet.
They came from Cisco, from Microsoft, from the teams that write the DNS software almost every network on Earth depends on. Paul Vixie, who had shepherded BIND — the most widely deployed DNS server in the world — for the better part of two decades, was there. So was a young researcher from IOActive named Dan Kaminsky, who had found the thing that put them all in the room. What Kaminsky had was a way to take over the name resolution of essentially any domain — your bank, your email provider, the software update server your laptop trusts — in a matter of seconds, from off to the side, without breaking a single cryptographic key. Because there weren’t any keys to break. DNS didn’t have them.
The remarkable part isn’t that the bug existed. It’s that the fix everyone shipped that July wasn’t a fix at all. It was a delay.
The 16-bit lock
To understand the panic, you have to understand how laughably thin the security of DNS was — and largely still is.
When your resolver asks an authoritative server “what’s the address for example.com?”, it sends a UDP packet and waits for a reply. The only thing tying the reply to the question is a 16-bit transaction ID — a number the resolver picks and the answer has to echo back. Sixteen bits is 65,536 possibilities. That’s it. That number, plus the fact that the answer has to arrive on the right UDP port, was the entire defense against someone forging a reply.
The classic attack was to race the real server: fire a flood of forged answers with guessed transaction IDs, hoping one lands before the legitimate reply does. It sounds easy, and it half was — but there was a catch that made it survivable. Once the real answer arrived, the resolver cached it, and for the length of the record’s TTL, it would stop asking. Guess wrong, and you had to wait — sometimes hours, sometimes a day — for the cache to expire before you got another shot at that name. One race per TTL. The odds were bad enough, and the reset slow enough, that DNS limped along on this for twenty-five years.
What Kaminsky actually found
Kaminsky’s insight was to stop attacking the name he wanted.
Instead of racing to poison www.bank.com — a record that, once legitimately cached, locks you out for hours — he had the victim resolver look up names that couldn’t be cached, because they didn’t exist: aaa.bank.com, then aab.bank.com, then aac.bank.com, on and on. Every one of those is a fresh query the resolver has never seen, so there’s nothing in the cache to block it. No waiting. He could run the race thousands of times a second.
Then came the second half, the part that turned a nuisance into a catastrophe. When he won a race — when one of his forged replies beat the real one — he didn’t just answer the question about aac.bank.com. He stuffed the authority section of the forged packet with a record saying, in effect, “and by the way, the nameserver for all of bank.com is over here, at this IP I control.” DNS calls this an in-bailiwick referral, and resolvers accepted it because it looked like it came from a server allowed to speak for that zone. Win one race against one meaningless subdomain, and you didn’t poison one record — you replaced the nameserver for the entire domain. Everything under bank.com now resolved to wherever the attacker said.
No TTL to wait out. No cryptography to defeat. Just enough forged UDP packets, which on a decent connection took seconds.
The patch that bought time
Here’s what makes this story worth retelling. The multi-vendor patch that shipped on July 8, 2008 — Microsoft, ISC’s BIND, Cisco, Red Hat, and more, all releasing on the same day by prior agreement — did not add authentication to DNS. It couldn’t. There was no way to retrofit real cryptographic verification into every resolver on the internet in a coordinated shot.
What it did was add a second number for the attacker to guess. Before Kaminsky, most resolvers sent all their queries from one predictable UDP source port, so the only variable was the 16-bit transaction ID. The patch made resolvers randomize the source port too — roughly another 16 bits of entropy. Now a forged reply had to match both the transaction ID and the right port, pushing the search space from about 65,000 to a few billion. The attack didn’t become impossible. It became slow enough to be impractical against a well-patched resolver. That’s a different thing, and everyone involved knew it.
Randomizing source ports is a stopgap in the same family as 0x20 encoding — randomly capitalizing the letters of the queried name so the answer has to echo the exact mix back. Both squeeze a few more bits of unpredictability out of a protocol that was never designed to resist a determined liar. They raise the cost of forgery; they don’t establish who’s telling the truth.
The leak
The disclosure had its own drama, and it’s a small lesson in how hard coordinated secrecy is.
Kaminsky asked the security community for a rare thing: sit on your curiosity for thirty days, patch quietly, and he’d explain everything at Black Hat in August. Most people obliged. Then, on July 21, the reverse-engineer Thomas Dullien — better known as Halvar Flake — publicly reasoned out the likely mechanism on his blog, from nothing but the shape of the patch and the size of the reaction. He got it essentially right. Within hours, the security firm Matasano, which had been briefed on the real details, published a post confirming his guess. They pulled it down within minutes, but the internet does not have an undo button. The full technique was out about two weeks before Kaminsky’s Black Hat talk on August 6, the details of which had by then already leaked to the audience.
The vulnerability got a name — CVE-2008-1447 — and, in the years since, the status of a genuine internet-scale near-miss.
We never actually fixed it
The uncomfortable coda is that the real fix was supposed to be DNSSEC, which signs DNS records so a resolver can verify they came from the zone’s actual owner and weren’t forged in transit. DNSSEC existed in 2008. It exists now. Adoption is still, depending on how you count, somewhere south of a third of zones — and validation on the resolver side is patchier still. The cryptographic answer to Kaminsky’s attack has been sitting on the shelf for the entire time we’ve been relying on the port-randomization workaround instead.
So the honest summary is this: in 2008 one researcher demonstrated that any name on the internet could be forged at will, a room full of vendors bought the internet some time with sixteen bits of extra randomness, and then most of the industry declined to install the actual lock. The Kaminsky attack isn’t a historical curiosity you patched and forgot. It’s the reason your resolver randomizes its source ports today — a twenty-five-year-old design still standing mostly because guessing a few billion combinations fast enough is annoying, and we agreed, quietly, that annoying was good enough.