Bugtraq mailing list archives

Re: preventing sequence number guessing


From: avalon () coombs anu edu au (Darren Reed)
Date: Wed, 25 Jan 1995 17:04:14 +1100 (EDT)



I'm certainly no security expert, but I had a fairly simple idea
for fixing the sequence number guessing vulnerability.  Hopefully
someone can tell me whether it's worthless or not.  Hunting season's
open -- shoot it down at will. :-)

When OS boots up, grab lots of entropy and use MD5 to hash it
into a 32 bit seed; initialize tcp_iss with it.  Now let the
kernel do its normal "increment tcp_iss a little for every new
connection and every couple of clock ticks" schtick as always.

This is a good start...

I've only got one novel idea: instead of using tcp_iss directly
for the SYN everytime a new TCP/IP connection is opened, send
MD5(tcp_iss) [or maybe MD5(tcp_iss, time(NULL), ...)].

not bad either...but rather than just when it is opened, perhaps
something a bit different but very similar...

This implements a cryptographically strong random number generator
for the sequence numbers; then attackers would have to invert
MD5 to predict sequence numbers.  MD5 is quite fast (is it fast
enough?) and is completely exportable.  Code for MD5 is available
for anonymous ftp on ripem.msu.edu /pub/crypt/other/md5.zip.

To nitpick, tcp_iss should be a full 64 bit (or even larger :-)
data type; this is easy enough to change in the kernel: (right?)

No.  For the patch to be most useful, it should work with minimal
alteration to .o's (I've learnt this) unless you're Sun/DEC, etc.
Even then, most people will be reluctant to make these sort of
changes unless they're confident about what they're doing.

[...]
So, am I missing some important kernel feature which shoots this
all down?  Or is this actually a worthwhile technique?  [If it
is worthwhile, it seems like it'd be pretty easy to code -- but
I have no experience at kernel programming, so I haven't done it
myself. <sigh>]

If you don't interfere with the generation of tcp_iss at the *right*
time (and remember, for some stupid reason to do with 4.2BSD, you're
limited to 31 bits) the kernel will hapily make tcp_iss 0 for you,
regardless of what your increments were in and what it started out at.

It would seem that the easiest way to "hijack" the generation of the
tcp_iss variable in the kernel is to mess with the table in in_proto.c
(which is shipped with all SunOS 4.1.x and is compiled when you generate
your own kernel).  Indeed, rather than use that program to mess with
ip_output.o and insert a wrapper, you can simply put your wrapper into
the table here and voila!  If, for example, we used the above idea,
it should be trivial to write a wrapper for tcp_input which set tcp_iss
to whatever only when it was a pure "SYN" packet coming in.  How hard
is that ?

MD5(foo)
tcp_seq foo;
{
        ...
        return bar;
}

tcp_input_wrap(m)
struct mbuf *m;
{
        struct ip *ip;
        struct tcphdr *tcp;

        ip = mtod(m, struct ip *);
        tcp = (struct tcphdr *)((char *)ip + ip->ip_hl << 2);
        if (tcp->th_flags == TH_SYN)
                tcp_iss = MD5(tcp_iss);
        return tcp_input(m);
}

and in in_proto.c, we replace tcp_input with tcp_input_wrap in the
table for SOCK_STREAM.  The rest is academic...

darren



Current thread: