]> The Tcpdump Group git mirrors - tcpdump/commitdiff
patch from George Bakos gbakos[AT]ists.dartmouth.edu:
authorhannes <hannes>
Sun, 15 Dec 2002 08:33:23 +0000 (08:33 +0000)
committerhannes <hannes>
Sun, 15 Dec 2002 08:33:23 +0000 (08:33 +0000)
A denial of service vulnerability exists in the print-bgp
module in the way IPv4 Withdrawal prefix lengths are validated. If IPv6 is
not enabled, the function decode_prefix4() is called to breakout the
prefix length and network prefix fields of the UPDATE message. In
bgp_update_print, a pointer (i) is incremented with the returned length
and thus traverses all withdrawn routes in the UPDATE message. However, if
the prefix length is > 32, decode_prefix4() returns -1. As the pointer "i"
then decrements, instead of incrementing, an infinite loop is created,
halting any further packet analysis and creating a very nice cpu sponge.

The patch addresses the loop problem, and also intervenes
whenever the length exceeds 32 bits (in IPv4) regardless
of message type:

print-bgp.c

index e8bdcbb67baa3fa9baa4114f929d7af4e9197200..989987510d0fdf6b375e87b84fb1eb2ad359e0a0 100644 (file)
@@ -36,7 +36,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-     "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.56 2002-12-11 07:13:58 guy Exp $";
+     "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.57 2002-12-15 08:33:23 hannes Exp $";
 #endif
 
 #include <tcpdump-stdinc.h>
@@ -876,7 +876,10 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
                             case SAFNUM_MULTICAST:
                             case SAFNUM_UNIMULTICAST:
                                 advance = decode_prefix4(tptr, buf, sizeof(buf));
-                                printf("\n\t      %s", buf);
+                               if (advance >= 0)
+                                       printf("\n\t      %s", buf);
+                               else 
+                                       printf("\n\t    (illegal prefix length)");
                                 break;
                             case SAFNUM_LABUNICAST:
                                 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
@@ -978,7 +981,10 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
                             case SAFNUM_MULTICAST:
                             case SAFNUM_UNIMULTICAST:
                                 advance = decode_prefix4(tptr, buf, sizeof(buf));
-                                printf("\n\t      %s", buf);
+                               if (advance >= 0) 
+                                       printf("\n\t      %s", buf);
+                               else
+                                       printf("\n\t    (illegal prefix length)");
                                 break;
                             case SAFNUM_LABUNICAST:
                                 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
@@ -1287,6 +1293,7 @@ bgp_update_print(const u_char *dat, int length)
                printf("\n\t  Withdrawn routes: %d bytes", len);
 #else
                char buf[MAXHOSTNAMELEN + 100];
+               int wpfx;
 
                TCHECK2(p[2], len);
                i = 2;
@@ -1294,8 +1301,14 @@ bgp_update_print(const u_char *dat, int length)
                printf("\n\t  Withdrawn routes:");
 
                while(i < 2 + len) {
-                       i += decode_prefix4(&p[i], buf, sizeof(buf));
-                       printf("\n\t    %s", buf);
+                       wpfx = decode_prefix4(&p[i], buf, sizeof(buf));
+                       if (wpfx >= 0) {
+                               i += wpfx;
+                               printf("\n\t    %s", buf);
+                       } else {
+                               printf("\n\t    (illegal prefix length)");
+                               break;
+                       }
                }
 #endif
        }
@@ -1340,10 +1353,13 @@ bgp_update_print(const u_char *dat, int length)
                while (dat + length > p) {
                        char buf[MAXHOSTNAMELEN + 100];
                        i = decode_prefix4(p, buf, sizeof(buf));
-                       printf("\n\t    %s", buf);
-                       if (i < 0)
+                       if (i >= 0) {
+                               printf("\n\t    %s", buf);
+                               p += i;
+                       } else {
+                               printf("\n\t    (illegal prefix length)");
                                break;
-                       p += i;
+                       }
                }
        }
        return;