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>