From owner-freebsd-security Wed Aug 23 09:34:36 1995 Return-Path: security-owner Received: (from majordom@localhost) by freefall.FreeBSD.org (8.6.11/8.6.6) id JAA11965 for security-outgoing; Wed, 23 Aug 1995 09:34:36 -0700 Received: from time.cdrom.com (time.cdrom.com [192.216.222.226]) by freefall.FreeBSD.org (8.6.11/8.6.6) with ESMTP id JAA11957 for ; Wed, 23 Aug 1995 09:34:33 -0700 Received: from localhost (localhost [127.0.0.1]) by time.cdrom.com (8.6.11/8.6.9) with SMTP id JAA08313 for ; Wed, 23 Aug 1995 09:34:30 -0700 Prev-Resent: Wed, 23 Aug 1995 09:34:29 -0700 Prev-Resent: "security@freebsd.org " Received: from freefall.FreeBSD.org (freefall.cdrom.com [192.216.222.4]) by time.cdrom.com (8.6.11/8.6.9) with ESMTP id JAA08300 for ; Wed, 23 Aug 1995 09:32:29 -0700 Received: from wc.cdrom.com (wc.cdrom.com [192.216.223.37]) by freefall.FreeBSD.org (8.6.11/8.6.6) with ESMTP id JAA11906 for ; Wed, 23 Aug 1995 09:32:27 -0700 Received: from who.cdrom.com (who.cdrom.com [192.216.223.34]) by wc.cdrom.com (8.6.12/8.6.12) with ESMTP id JAA01579 for ; Wed, 23 Aug 1995 09:32:06 -0700 Received: from narq.avian.org (wet-string.avian.org [199.103.168.126]) by who.cdrom.com (8.6.11/8.6.11) with ESMTP id JAA24187 for ; Wed, 23 Aug 1995 09:32:08 -0700 Received: (from hobbit@localhost) by narq.avian.org (8.6.12/_H*) id KAA13102 for jkh@cdrom.com; Wed, 23 Aug 1995 10:05:23 -0400 Date: Wed, 23 Aug 1995 10:05:23 -0400 From: *Hobbit* Message-Id: <199508231405.KAA13102@narq.avian.org> To: jkh@cdrom.com Subject: quick question Resent-To: security@freebsd.org Resent-Date: Wed, 23 Aug 1995 09:34:30 -0700 Resent-Message-ID: <8311.809195670@time.cdrom.com> Resent-From: "Jordan K. Hubbard" Sender: security-owner@freebsd.org Precedence: bulk are you guys aware of the possibility that Freebsd kerberized "rcp" silently fails to encrypt the data when invoked with the "-x" option? If you're not the right person to ask I'll be happy to fire off a discussion with whoever's overseeing that code. Integrating kerberos stuff is great, but should be tested carefully! _H* From owner-freebsd-security Thu Aug 24 20:50:04 1995 Return-Path: security-owner Received: (from majordom@localhost) by freefall.FreeBSD.org (8.6.11/8.6.6) id UAA21383 for security-outgoing; Thu, 24 Aug 1995 20:50:04 -0700 Received: from puli.cisco.com (puli.cisco.com [171.69.1.174]) by freefall.FreeBSD.org (8.6.11/8.6.6) with ESMTP id UAA21375 for ; Thu, 24 Aug 1995 20:50:01 -0700 Received: from localhost.cisco.com (localhost.cisco.com [127.0.0.1]) by puli.cisco.com (8.6.8+c/8.6.5) with SMTP id UAA18773; Thu, 24 Aug 1995 20:47:39 -0700 Message-Id: <199508250347.UAA18773@puli.cisco.com> To: Paul A Vixie Cc: mogul@pa.dec.com, root@iifeak.swan.ac.uk, bugtraq@crimelab.com, freebsd-security@freebsd.org Subject: Re: Jeffrey Mogul: Re: screend IP firewall bug In-Reply-To: Your message of "Thu, 24 Aug 1995 13:42:15 PDT." <9508242042.AA11439@gw.home.vix.com> Date: Thu, 24 Aug 1995 20:47:38 -0700 From: Paul Traina Sender: security-owner@freebsd.org Precedence: bulk The proposed fixes do not solve the problems (at least in the Reed/Ugen firewall code (it's originally written by Darren Reed, who -discovered- the first varient of this bug)). I came up with a simple solution that solves all the attack varients I could come up with, including out of order packets, garbage in the packet, and overlapping data. There is NO need for minimum sized header length checks. The fix that fixes all known attacks is to simply deny any TCP, and ONLY TCP, (this is not a typo), packet that has the FO field equal to 1. I would strongly advise NOT applying any fix based upon the scenario analysis performed by root@ifreak.swan.ac.uk, as it is incomplete and based upon an IP implementation that has not been shown to conform to the BSD implementation in packet reassembly (in -any- case, I don't want to assume only linux boxes live behind my firewall). Given that screend has (was?) well behaved has it kept state of packets that were fragmented, I do not believe all of the attack methods that could be used against less sophisticated firewalls, such as the code present in FreeBSD and Linux distribution, could ever have been applied to screend. Nevertheless, I would advise putting in the fix I proposed above to screend. From: Paul A Vixie Subject: Jeffrey Mogul: Re: screend IP firewall bug this is what we were discussing, yes? ------- Forwarded Message Delivery-Date: Thu, 24 Aug 1995 12:18:42 -0700 Return-Path: mogul@pa.dec.com Received: by gw.home.vix.com id AA04500; Thu, 24 Aug 95 12:18:41 -0700 Received: from acetes.pa.dec.com by mail1.digital.com; (5.65 EXP 4/12/95 for >>V3.2/1.0/WV) id AA14951; Thu, 24 Aug 1995 11:59:56 -0700 Received: by acetes.pa.dec.com; id AA02142; Thu, 24 Aug 95 11:59:55 -0700 Message-Id: <9508241859.AA02142@acetes.pa.dec.com> To: Richard Black Cc: mogul@pa.dec.com, paul@vix.com Subject: Re: screend IP firewall bug In-Reply-To: Your message of "Thu, 24 Aug 95 17:58:41 BST." <"swa >>n.cl.cam.:136610:950824165853"@cl.cam.ac.uk> Date: Thu, 24 Aug 95 11:59:54 MDT From: Jeffrey Mogul The included message describes a bug in some "vendor"s' IP firewalling code which was discussed on a linux group. Having seen it I decided to check out the Ultrix and OSF1 firewalling code (screend). It seems to have a similar hole. This fact is irrelevant as far as we are concerned because we don't use screend here, but it seemed like a good idea for me to report it to somewhere. Since you wrote it you seemed like a good choice. The only source I have access to is Ultrix 4.3 and OSF1 V2.0 so if its been fixed since then, then appologies in advance. Paul, the original report is appended below. Richard, this is the first I've heard of this bug. Thanks for reporting it. As far as I can tell, though, the fix included solves a different problem from the attack mentioned in "root"'s message. There seem to be two different kinds of attack: (1) send a fragment starting at offset 8 that overlaps header fields which have already been checked. (2) send a first packet whose tot_len field is too small, so that the firewall checks fields that the reassembler does not include in the final packet. Am I confused, or does the proposed fix not solve #1 if the reassembler uses an algorithm that allows overwriting of overlapping packets? Paul, for use in screend I would suggest the code appended after the forwarded message. - -Jeff - - ---------- Forwarded message ---------- Date: Wed, 23 Aug 1995 10:24:58 +0100 (BST) From: System Administrator To: bugtraq@crimelab.com Cc: linux-security@tarsier.cv.nrao.edu Subject: IP firewalling bugs A variety of systems based on the Ugen firewall code (FreeBSD/Linux probably NetBSD) are vulnerable to the following reported attack: Send an IP fragment 0 acceptable to the firewall Send an IP fragment at offset 8 to rewrite most of the header and all the data For Linux at least the IP header should not be vulnerable to overwriting because of the way the fragment merging is done. The following is a provisona >>l not very tested fix (I only found out about the bug 30 minutes ago). Linux is only vulnerable to tcp/udp header overwriting so host level blocking is unaffected. Because the Ugen firewall is virtually PD a variety of low end routers seem to use it and may also be affected. I will be issuing a tested fix to Linus for 1.2.14 once he returns from sunni >>ng himself. [This fix is of course GPL'd and Linux but the BSD fix should be similar and obvious] - - --- ip_fw.c Thu Jun 29 17:18:52 1995 +++ /tmp/ip_fw.c Wed Aug 23 10:11:22 1995 @@ -209,6 +209,30 @@ */ frag1 = ((ntohs(ip->frag_off) & IP_OFFSET) == 0); + + /* + * Stop any lead fragment attacks (eg sending the IP header + * and then overwriting it with a new fragment). The fragmenter + * works correctly to stop the rest of this attack. + */ + + if(frag1) + { + switch(ip->protocol) + { + case IPPROTO_UDP: + if(ip->ihl<<2+sizeof(struct udphdr) + >ntohs(ip->tot_len)) + return 0; + break; + case IPPROTO_TCP: + if(ip->ihl<<2+sizeof(struct udphdr) + >ntohs(ip->tot_len)) + return 0; + break; + } + } + if (!frag1 && (opt != 1) && (ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)) return(1); - ------- End of Forwarded Message *** unpack.c Sat Aug 19 02:55:28 1995 - --- unpack.c.maybe Thu Aug 24 11:58:42 1995 *************** *** 131,149 **** if (ipp->ip_off & IPOFF_MASK) { /* do we have to look for fragment leader */ switch (ipp->ip_p) { - - case IPPROTO_UDP: - - case IPPROTO_TCP: - - case IPPROTO_ICMP: /* * For these protocols, we parse into the "ip data" * segment, so we need information out of fragment * 0. */ ! return(FindFragLeader(ipp, unpp)); default: /* Other protocols: all fragments have enough info */ break; /* drop through */ } } - --- 131,187 ---- if (ipp->ip_off & IPOFF_MASK) { /* do we have to look for fragment leader */ + int offbytes = ipp->ip_off <<= 3; + switch (ipp->ip_p) { /* * For these protocols, we parse into the "ip data" * segment, so we need information out of fragment * 0. + * WARNING: this code assumes NO IP OPTIONS ALLOWED. + * If you change this, the length calculations need + * to be based on stored IP header lengths! */ ! case IPPROTO_UDP: ! if (offbytes >= (sizeof(struct ip) + sizeof(struct udphdr)) ! return(FindFragLeader(ipp, unpp)); ! else { ! if (debug) ! fprintf(stderr, ! "UDP fragment overlaps headers, off %d\n", ! offbytes); ! return(0); ! } ! case IPPROTO_TCP: ! if (offbytes >= (sizeof(struct ip) + sizeof(struct tcphdr)) ! return(FindFragLeader(ipp, unpp)); ! else { ! if (debug) ! fprintf(stderr, ! "TCP fragment overlaps headers, off %d\n", ! offbytes); ! return(0); ! } ! case IPPROTO_ICMP: ! if (offbytes >= (sizeof(struct ip) + MinIcmpLen) ! return(FindFragLeader(ipp, unpp)); ! else { ! if (debug) ! fprintf(stderr, ! "ICMP fragment overlaps headers, off %d\n", ! offbytes); ! return(0); ! } default: /* Other protocols: all fragments have enough info */ + if (offbytes < sizeof(struct ip)) { + if (debug) + fprintf(stderr, + "IP fragment overlaps headers, off %d\n", + offbytes); + return(0); + } break; /* drop through */ } } *************** *** 156,161 **** - --- 194,204 ---- sizeof(*udpp) - remlen); return(0); } + if (((ipp->ip_hl<<2) + (sizeof(struct udphdr))) > ipp->ip_len) { + if (debug) + fprintf(stderr, "UDP ip_len %d too short\n", ipp->ip_len); + return(0); + } udpp = (struct udphdr *)ipdata; unpp->src.port = ntohs(udpp->uh_sport); unpp->dst.port = ntohs(udpp->uh_dport); *************** *** 168,173 **** - --- 211,221 ---- sizeof(*tcpp) - remlen); return(0); } + if (((ipp->ip_hl<<2) + (sizeof(struct tcphdr))) > ipp->ip_len) { + if (debug) + fprintf(stderr, "TCP ip_len %d too short\n", ipp->ip_len); + return(0); + } tcpp = (struct tcphdr *)ipdata; unpp->src.port = ntohs(tcpp->th_sport); unpp->dst.port = ntohs(tcpp->th_dport); *************** *** 179,184 **** - --- 227,237 ---- if (debug) fprintf(stderr, "Runt ICMP header (%d short)\n", MinIcmpLen - remlen); + return(0); + } + if (((ipp->ip_hl<<2) + (sizeof(struct icmp))) > ipp->ip_len) { + if (debug) + fprintf(stderr, "ICMP ip_len %d too short\n", ipp->ip_len); return(0); } icmpp = (struct icmp *)ipdata; ------- End of Forwarded Message