At IETF 72 in Dublin I gave a demonstration of DNS spoofing based on the attack on DNS described by Dan Kaminsky. I was able to successfully inject a fake DNS record in to the cache of a name server with a fixed port in a few seconds and sometimes in well under a second.

Bert Hubert published a description of the math behind this attack on namedroppers and I have been playing with the spoofer to see how close I can get the experiment and theory.

I ran my spoofer on a network consisting of three machines linked by a cheap gigabit switch. The attacker was on a Mac Pro, the target nameserver was on a Mac Book Pro and the authoritative server, that the attacker was pretending to be, was on a old FreeBSD box (100Mb). I used DUMMYNET to simulate a longer link to the authoritative server (delay = 30ms).

I ran the spoofer 1000 times and plotted a histogram of the frequency of success against time.

The pink bar shows the median of all the times recorded. If I recall my A level maths correctly, this should coincide with the 50% chance of success predicted by the math.

The math presented by Bert Hubert considers the expansion of the binomial

Ps = probability of success on a single attempt

Pf = probability of failure on a single attempt

( Ps + Pf )^n = 1

Expanding this and remembering that the sum of all the terms containing success = (1- the term for always failing) leads to the probability of combined success

Pcs(n) = 1 – (1 – Ps)^(n)

We know that n = T/W so we get

Pcs(t) = 1 – (1 – Ps)^(t/W)

Bert Hubert tells us that Ps = (D*R*W)/(N*P*I) where

I: Number distinct IDs available (maximum 65536)

P: Number of ports used (maximum around 64000 as ports under 1024

are not always available, but often 1)

N: Number of authoritative nameservers for a domain (averages

around 2.5)

R: Number of packets sent per second by the attacker

W: Window of opportunity, in seconds. Bounded by the response

time of the authoritative servers (often 0.1s)

D: Average number of identical outstanding queries of a resolver

(typically 1, see Section 5)

I used the following values

I=65535

R=36000 – From looking at the traffic I was sending

W=0.030 – From the settings I gave DUMMYNET

N=1.0 (I fixed this)

P=1 (I fixed this)

D=1

Plotting this on the same graph as the histogram gives:

The blue circles are the predicted probability of combined success (Their y axis runs from 0 to 1 and is not shown). As you can see the predicted 50% chance (black cross lines) occurs slightly before the median but it is fairly close.

In order to improve things I added an extra term to the equation to account for the time that the window is closed (This is due to the spoofer taking a bit of time to notice that it has been unsuccessful and to try again). So:

n = T/(W+Wc)

Ps = (D*R*W))/(N*P*I)

where Wc is measured to be about 0.003 seconds. The graph now looks like

That seems like good agreement to me. The median in this case is 1386ms.

BTW: The graphs were plotted using R. This is the code I used

#Plot a histogram of frequency of success against time mydata <- read.table("/tmp/speed-test-30ms",header=TRUE) #Plot both on a single graph h <- hist(mydata$time,breaks=100,plot=FALSE) plot(h,freq=FALSE, xlim=range(h$mids),ylim=range(h$density), sub="Histogram showing time to success of real spoofer (pink line shows median)", main="DNS Spoofer Performance", ylab="Density", xlab="Time/ms") abline(v=median(mydata$time),col=70) #Plot Bert Hubert's math D=1.0 R=36000.0 W=0.030 Wc=0.003 N=1.0 P=1 I=65535 Ps <- ((D*R*W)/(N*P*I)) Pcs <- function(t){1 - (1 - Ps)**((t/1000)/(W+Wc))} par(new=TRUE) nx <- sample(h$mids) y=Pcs(nx) #Scale plot to same as histogram my=max(y) ny=y*max(h$density)/my plot(nx,ny, xlim=range(h$mids),ylim=range(h$density),col="blue", ann=FALSE) #Calculate time for 0.5 chance time5 = 1000*(W+Wc)*(log10(0.5)/log10(1 - Ps)) abline(v=time5) abline(h=0.5*max(h$density)/my)

## Wouter

Pingback: intir.net » Blog Archive » Why DNS is Broken, in Plain English