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>
index | next in thread | previous in thread | raw e-mail
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
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.10.10001210638530.11627-100000>
