Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 21 Jan 2000 06:43:54 -0500 (EST)
From:      Omachonu Ogali <oogali@intranova.net>
To:        Brett Glass <brett@lariat.org>
Cc:        security@freebsd.org
Subject:   Re: stream.c worst-case kernel paths
Message-ID:  <Pine.BSF.4.10.10001210638530.11627-100000@hydrant.intranova.net>
In-Reply-To: <4.2.2.20000120182425.01886ec0@localhost>

next in thread | previous in thread | raw e-mail | index | archive | help
Would this work:

-- start --
--- tcp_input.c	Tue Apr 20 15:09:15 1999
+++ tcp_input.c.new	Fri Jan 21 06:30:13 2000
@@ -398,7 +398,27 @@
 			    "Connection attempt to TCP %s:%d from %s:%d\n",
 			    buf, ntohs(ti->ti_dport), inet_ntoa(ti->ti_src),
 			    ntohs(ti->ti_sport));
+		} else if (tiflags & TH_ACK) {
+			/*
+			 * Alpha code in response to stream.c
+			 * - Omachonu Ogali <oogali@intranova.net>
+			 */
+
+			char buf[4*sizeof "123"];
+
+			strcpy(buf, inet_ntoa(ti->ti_dst));
+			log(LOG_INFO,
+			    "received TCP/ACK to non existant connection: %s:%d -> %s:%d\n",
+			    inet_ntoa(ti->ti_src), ntohs(ti->ti_sport), buf, ntohs(ti->ti_dport));
+
+			/*
+			 * Drop without reset to prevent smurf-like tcp
+			 * attack
+			 */
+
+			goto drop;
 		}
+			
 #ifdef ICMP_BANDLIM
 		if (badport_bandlim(1) < 0)
 			goto drop;
-- stop --

Omachonu Ogali
Intranova Networking Group

On Thu, 20 Jan 2000, Brett Glass wrote:

> I've been browsing the code, and have seen two possible places where
> the code might be improved to lessen the impact of this DoS. Folks
> who know the stack better may know about details and side effects
> that I don't, so so if my analysis has holes in it please don't chew 
> me out TOO badly.
> 
>  From /sys/netinet/tcp_input.c:
> 
> The kernel seeks a socket that matches the packet. It fails, of course,
> to find an open socket.
> 
>          inp = in_pcblookup_hash(&tcbinfo, ti->ti_src, ti->ti_sport,
>              ti->ti_dst, ti->ti_dport, 1);
> 
> If the system isn't listening on the port, inp is set to NULL. But inside
> in_pcblookup_hash, we've had to do two hash table lookups, because
> the "wildcard" flag is set to 1. (Suggested improvement: turn off the
> wildcard search if the packet is not a SYN. I suppose that if the
> packet IS a SYN, we still have to test to see if it was erroneously
> sent in the middle of a connection, so we really have to do both tests 
> in that case. See in_pcb.c.)
> 
> Back to tcp_input.c. We then execute the following:
> 
>          if (inp == NULL) {
>                  if (log_in_vain && tiflags & TH_SYN) {
>                          char buf[4*sizeof "123"];
> 
>                          strcpy(buf, inet_ntoa(ti->ti_dst));
>                          log(LOG_INFO,
>                              "Connection attempt to TCP %s:%d from %s:%d\n",
>                              buf, ntohs(ti->ti_dport), inet_ntoa(ti->ti_src),
>                              ntohs(ti->ti_sport));
>                  }
>                  }
> #ifdef ICMP_BANDLIM
>                  if (badport_bandlim(1) < 0)
>                          goto drop;
> #endif
>                  goto dropwithreset;
>          }
> 
> Normally, we'll wind up at the label "dropwithreset", which means we'll send back a RST.
> This suggests that restricting RSTs will help with the DoS. (Does anyone know if
> not sending an RST violates any RFCs if there was never a connection?)
> 
> Trouble is, a smart attacker will fire the barrage at a port on which the machine is
> listening. This makes the code path longer because the hash table lookup will succeed.
> We execute:
> 
>          tp = intotcpcb(inp);
>          if (tp == 0)
>                  goto dropwithreset;
>          if (tp->t_state == TCPS_CLOSED)
>                  goto drop;
> 
>          /* Unscale the window into a 32-bit value. */
>          if ((tiflags & TH_SYN) == 0)
>                  tiwin = ti->ti_win << tp->snd_scale;
>          else
>                  tiwin = ti->ti_win;
> 
>          so = inp->inp_socket;
>          if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) {
> #ifdef TCPDEBUG
>                  if (so->so_options & SO_DEBUG) {
>                          ostate = tp->t_state;
>                          tcp_saveti = *ti;
>                  }
> #endif
>                  if (so->so_options & SO_ACCEPTCONN) {
>                          register struct tcpcb *tp0 = tp;
>                          struct socket *so2;
>                          if ((tiflags & (TH_RST|TH_ACK|TH_SYN)) != TH_SYN) {
>                                  /*
>                                   * Note: dropwithreset makes sure we don't
>                                   * send a RST in response to a RST.
>                                   */
>                                  if (tiflags & TH_ACK) {
>                                          tcpstat.tcps_badsyn++;
>                                          goto dropwithreset;
>                                  }
>                                  goto drop;
> 
> At which point the packet is dropped, since tiflags & (TH_RST|TH_ACK|TH_SYN)) != TH_SYN
> (that is, it's not a SYN). But we've had to attempt two hash table lookups (we could have done 
> only one if we'd tested for a SYN) and send the RST unless we've disabled it. Worse still, if 
> we send the RSTs, we may have to handle an ICMP "unreachable" message from the router if the 
> source address is spoofed.
> 
> So, the two obvious optimizations are to add a test for SYNs prior to the hash table lookup and
> not to send a RST back.
> 
> --Brett
> 
> 
> 
> 
> 
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-security" in the body of the message
> 



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-security" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.10.10001210638530.11627-100000>