Recently, two detailed attack methods against TCP/IP's Initial Sequence Numbers were published:
- CERT Advisory CA-2001-09 "Statistical Weaknesses in TCP/IP Initial Sequence Numbers"
- Michal Zalewski "Strange Attractors and TCP/IP Sequence Number Analysis"
Predicting an ISN takes two steps:
- Obtain a series of generated ISN values.
- Try and predict the next ISN that may be used by the server
This program achieves the first step by displaying ISN numbers of a remote server.
The second step, the statistical prediction, is not done in this program. If you are a statistical expert, you may want to complete this program and publish it.
To compile:
# gcc -o ISNprint ISNprint.c -llcrzo -lpcap
isn_pid=fork();
if (isn_pid<0) return(LCRZO_ERR_FUFORK);
if (isn_pid==0)
{ /* this process sends a SYN (we left to our computer the job to send
a RST) */
/* in case we receive a signal */
signal(SIGINT, isn_sig_received1);
lcrzo_epr(isn_sendsyn(device, clientetha, destetha,
clientipl, serveripl, serverport,
startingclientport, startingclientseqnum));
/*never reatched*/
}
else
{ /* this process sniff and prints sequence numbers */
/* in case we receive a signal */
signal(SIGINT, isn_sig_received2);
lcrzo_epr(isn_print(device, clientetha, destetha,
clientipl, serveripl, serverport,
startingclientport, startingclientseqnum));
/*never reatched*/
}
/* never reatched */
return (0);
}
/*-------------------------------------------------------------*/
void isn_sig_received1(int i)
{ int language;
/* spoof */
lcrzo_epr(lcrzo_spoof_init(&isn_spoof));
while(1)
{ lcrzo_epr(lcrzo_spoof_ethipopttcpoptdata(&isn_spoof, device, hdrleth,
hdrlip, NULL, 0,
hdrltcp, NULL, 0,
NULL, 0));
hdrltcp.sport=clientport++;
hdrltcp.seqnum=clientseqnum; clientseqnum+=10;
/* you may want to remove this sleep, if you own the server */
lcrzo_epr(lcrzo_time_sleep(100000));
}
/*never reatched*/
return(LCRZO_ERR_IEINTERNALERROR);
}
/* try to decode it */
ret=lcrzo_packet_decodem_ethipopttcpoptdata(sniffdata, sniffdatasize,
&hdrleth, &hdrlip, NULL, NULL,
&hdrltcp, NULL, NULL,
NULL, NULL);
if ( ret!=LCRZO_ERR_OK )
return(LCRZO_ERR_OK);
/* only count synack */
if ( ! (hdrltcp.syn && hdrltcp.ack) )
return(LCRZO_ERR_OK);
/* check if the addresses are the one we are looking for */
if ( ! lcrzo_etha_equal(hdrleth.src, destetha) )
return(LCRZO_ERR_OK);
if ( ! lcrzo_etha_equal(hdrleth.dst, clientetha) )
return(LCRZO_ERR_OK);
if ( ! lcrzo_ipl_equal(hdrlip.saddr, serveripl) )
return(LCRZO_ERR_OK);
if ( ! lcrzo_ipl_equal(hdrlip.daddr, clientipl) )
return(LCRZO_ERR_OK);
/* check server port */
if ( hdrltcp.sport!=serverport )
return(LCRZO_ERR_OK);
/* now this seems ok, but we verify with starting values */
diff1=hdrltcp.dport-startingclientport;
diff2=(hdrltcp.acknum-1-startingclientseqnum)/10;
if ( diff1!=diff2 )
return(LCRZO_ERR_OK);
/* now, it's OK, so we print the seqnum */
printf("% 6ld : %.10lu\t[diff ", diff1, hdrltcp.seqnum);
if (hdrltcp.seqnum>=oldseqnum)
printf("+%.10lu]\n", hdrltcp.seqnum-oldseqnum);
else
printf("-%.10lu]\n", oldseqnum-hdrltcp.seqnum);
oldseqnum=hdrltcp.seqnum;