Bugtraq mailing list archives

Re: Recent troubles


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



Someone replied to my

If I had source, I'd probably corrupt tcp_iss on not only received
packets but also [...].

with

You should read RFC 793 (if you haven't).

This was all; there was no indication _what_ in RFC793 was felt
relevant.  (RFC793 is the TCP spec.)

I did, but not to the list.  But anyway...

I assume the section being talked about is the following part of 3.3;
this is a serious enough point that I think it's worth sending this to
the whole list, especially since I didn't mention this with the code I
posted.

+----------------
| Initial Sequence Number Selection
|
| The protocol places no restriction on a particular connection being
| used over and over again.  A connection is defined by a pair of
| sockets.  New instances of a connection will be referred to as
| incarnations of the connection.  The problem that arises from this is
| -- "how does the TCP identify duplicate segments from previous
| incarnations of the connection?"  This problem becomes apparent if
| the connection is being opened and closed in quick succession, or if
| the connection breaks with loss of memory and is then reestablished.
|
| To avoid confusion we must prevent segments from one incarnation of a
| connection from being used while the same sequence numbers may still
| be present in the network from an earlier incarnation.  We want to
| assure this, even if a TCP crashes and loses all knowledge of the
| sequence numbers it has been using.  When new connections are
| created, an initial sequence number (ISN) generator is employed which
| selects a new 32 bit ISN.  The generator is bound to a (possibly
| fictitious) 32 bit clock whose low order bit is incremented roughly
| every 4 microseconds.  Thus, the ISN cycles approximately every 4.55
| hours.  Since we assume that segments will stay in the network no
| more than the Maximum Segment Lifetime (MSL) and that the MSL is less
| than 4.55 hours we can reasonably assume that ISN's will be unique.
+----------------

Yes, the tactic I described (and implemented) for generating
harder-to-guess ISNs violates this spec.  Like any method that
generates "random" ISNs, it runs the risk that old segments may be
mistaken for data on newly-established connections.

Several factors combine to make me ignore this risk.

First is that, assuming the method does generate reasonably random
ISNs, it's unlikely.  For a 4K maximum window size, it would require a
one-in-a-million coincidence (4G/4K), and even then it would have to
hit all the unlikely items below.  (For fat-pipe TCP, the chance is
higher; for a half-meg window, for example, it's more like one in
8192.)

how quickly can you send 1MB of data from host to host ?
10 seconds (best) ?

Third is that the new connection must use exactly the same port numbers
as the old.  Unless the other end of the connection crashes too, this
is extremely unlikely because it will have a TIME_WAIT socket sitting
around preventing this.

What about SO_REUSEADDR or do you disable this in all programs you
compile ? (A lot enable it to stop TIME_WAIT connections building up in
the kernel).

Fourth is the quiet time on TCP reboot, specifically for old segments
to run out of TTL.  If and when machines reboot fast enough for this to
be a problem, their TCPs need to be taught about this anyway, and that
should take care of it.

eh ? TTL rarely works as you say...nearly always a hop count thing.

Thus, I'll take the resistance to known attacks over the small risk
that two simultaneous host crashes, a very peculiar routing glitch,
extremely accelerated reboots, and a fluke somewhere between one in
8192 and one in 2^20 all conflue to corrupt a connection.

You may choose differently.  You're welcome to.

Unless of course you can suggest some better solution, something I can
implement in (say) less than 48 hours (my defense was done the same
afternoon I did the defense against LKMs and /dev/*mem).  I agree that
TCP needs to be redesigned...but that's not much help when machines are
being attacked _today_.  I'll be glad to talk redesign, once I have
some insulation against existing crackers.

Oh, I thought it was obvious, just ensure that the seq# changes more
often than it does and with some (large) uncertainty.  Although you have
a nice CRC algorithm there, it (a) doesn't appear to handle the case
where tcp_iss should wrap (TCP_COMPAT_42) (b) can be calculated.  Every
so often, despite your attempts, it will go back to 0 (tcp_iss) and from
there you can do the math yourself.  So the game becomes to get a packet
to be the first in after tcp_iss goes back to 0...the crackers have your
code, they can do the math themselves.

Surely there is a timing routing in the kernel somewhere which you could
plug a bit of extra assembly in...



Current thread: