From owner-freebsd-security Fri Jan 21 6:15:41 2000 Delivered-To: freebsd-security@freebsd.org Received: from cairo.anu.edu.au (cairo.anu.edu.au [150.203.224.11]) by hub.freebsd.org (Postfix) with ESMTP id 868441517B for ; Fri, 21 Jan 2000 06:15:34 -0800 (PST) (envelope-from avalon@cairo.anu.edu.au) Received: (from avalon@localhost) by cairo.anu.edu.au (8.9.3/8.9.3) id BAA12772; Sat, 22 Jan 2000 01:15:32 +1100 (EST) From: Darren Reed Message-Id: <200001211415.BAA12772@cairo.anu.edu.au> Subject: Re: stream.c worst-case kernel paths To: oogali@intranova.net (Omachonu Ogali) Date: Sat, 22 Jan 2000 01:15:32 +1100 (Australia/NSW) Cc: brett@lariat.org (Brett Glass), security@FreeBSD.ORG In-Reply-To: from "Omachonu Ogali" at Jan 21, 2000 06:43:54 AM X-Mailer: ELM [version 2.5 PL1] MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Sender: owner-freebsd-security@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org This patch has no rate limiting. I'd hate to think what 100,000 packets in 10 seconds would do to your system with this patch. Darren In some mail from Omachonu Ogali, sie said: > > 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 > + */ > + > + 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 > To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-security" in the body of the message