Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:4938
HistoryAug 04, 2003 - 12:00 a.m.

[SECURITY] Netfilter Security Advisory: NAT Remote DOS (SACK mangle)

2003-08-0400:00:00
vulners.com
7
              Netfilter Core Team Security Advisory
              
                       CVE: CAN-2003-0467

Subject:

Netfilter / NAT Remote DoS

Released:

01 Aug 2003

Effects:

Under limited circumstances, a remote user may be able to crash a
machine doing Network Address Translation (NAT).

Estimated Severity:

Medium.

Systems Affected:

Linux 2.4.20 kernels and recent 2.5 kernels with
CONFIG_IP_NF_NAT_FTP or CONFIG_IP_NF_NAT_IRC enabled, or the
ip_nat_ftp or ip_nat_irc modules loaded, on which ftp and irc users
are not packet filtered out.

Solution:

BEST: Upgrade to Linux kernels 2.4.21 (stable), or apply the patch below.

OR: As a workaround, the modules can be removed, or iptables can
be used to block untrusted users from initiating ftp or irc
connections through the NAT machine.

Details:

This was verified by Rusty Russell on 2.4.20, and verified fixed
with this patch.

Vendor Statement:

Red Hat: All of the 2.4.20-based kernels shipped by Red Hat already
contain the patch and are not vulnerable to this issue.
Others: unknown

Credits:
The problem was found, and the fix implemented by the Netfilter Core Team.

Contact:
[email protected]

diff -urpN --exclude TAGS -X
/home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal
linux-2.4.21-pre7/net/ipv4/netfilter/ip_nat_helper.c
working-2.4.21-pre7-sackadjust/net/ipv4/netfilter/ip_nat_helper.c
— linux-2.4.21-pre7/net/ipv4/netfilter/ip_nat_helper.c 2003-04-06
15:26:48.000000000 +1000
+++ working-2.4.21-pre7-sackadjust/net/ipv4/netfilter/ip_nat_helper.c 2003-04-14
23:18:38.000000000 +1000
@@ -366,54 +365,49 @@ sack_adjust(struct tcphdr *tcph,
}

-/* TCP SACK sequence number adjustment, return 0 if sack found and adjusted /
-static inline int
+/
TCP SACK sequence number adjustment. */
+static inline void
ip_nat_sack_adjust(struct sk_buff *skb,

  •                   struct ip_conntrack *ct,
    
  •                   enum ip_conntrack_info ctinfo)
    
  •              struct ip_conntrack *ct,
    
  •              enum ip_conntrack_info ctinfo)
    

{

  •   struct iphdr *iph;
      struct tcphdr *tcph;
    
  •   unsigned char *ptr;
    
  •   int length, dir, sack_adjusted = 0;
    
  •   unsigned char *ptr, *optend;
    
  •   unsigned int dir;
    
  •   iph = skb->nh.iph;
    
  •   tcph = (void *)iph + iph->ihl*4;
    
  •   length = (tcph->doff*4)-sizeof(struct tcphdr);
    
  •   tcph = (void *)skb->nh.iph + skb->nh.iph->ihl*4;
    
  •   optend = (unsigned char *)tcph + tcph->doff*4;
      ptr = (unsigned char *)(tcph+1);
    
      dir = CTINFO2DIR(ctinfo);
    
  •   while (length > 0) {
    
  •           int opcode = *ptr++;
    
  •   while (ptr < optend) {
    
  •           int opcode = ptr[0];
              int opsize;
    
              switch (opcode) {
              case TCPOPT_EOL:
    
  •                   return !sack_adjusted;
    
  •                   return;
              case TCPOPT_NOP:
    
  •                   length--;
    
  •                   ptr++;
                      continue;
              default:
    
  •                   opsize = *ptr++;
    
  •                   if (opsize > length) /* no partial opts */
    
  •                           return !sack_adjusted;
    
  •                   opsize = ptr[1];
    
  •                    /* no partial opts */
    
  •                   if (ptr + opsize > optend || opsize < 2)
    
  •                           return;
                      if (opcode == TCPOPT_SACK) {
                              /* found SACK */
                              if((opsize >= (TCPOLEN_SACK_BASE
                                             +TCPOLEN_SACK_PERBLOCK)) &&
                                 !((opsize - TCPOLEN_SACK_BASE)
                                   % TCPOLEN_SACK_PERBLOCK))
    
  •                                   sack_adjust(tcph, ptr-2,
    
  •                                   sack_adjust(tcph, ptr,
                                                  &ct->nat.info.seq[!dir]);
    
  •                           sack_adjusted = 1;
                      }
    
  •                   ptr += opsize-2;
    
  •                   length -= opsize;
    
  •                   ptr += opsize;
              }
      }
    
  •   return !sack_adjusted;
    

}

/* TCP sequence number adjustment */

  • Harald Welte <[email protected]> http://www.netfilter.org/
    ============================================================================
    "Fragmentation is like classful addressing – an interesting early
    architectural error that shows how much experimentation was going
    on while IP was being designed." – Paul Vixie
Related for SECURITYVULNS:DOC:4938