tcpdump mailing list archives

more print-bgp issues


From: George Bakos <gbakos () ists dartmouth edu>
Date: Sun, 15 Dec 2002 00:13:54 -0500

A denial of service vulnerability exists in the new (> Dec 11 cvs) 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.
Correct behavior (and I believe, the original intent) would be to trap the
-1 return value and break out of the decode.

In the packet below, I have specified a withdrawn route prefix length of
33 bits; clearly nonsensical for IPv4. The commandline tcpdump -nvs0 (or
any other snaplen large enough for a full decode), or reading from a file,
results in the loop:

[gbakos@lt1 gbakos]$ xxd /tmp/bgpkiller 
0000000: d4c3 b2a1 0200 0400 0000 0000 0000 0000  ................
0000010: ffff 0000 0100 0000 2251 fa3d 2a78 0400  ........"Q.=*x..
0000020: 5900 0000 5900 0000 0004 5a4e e894 0000  Y...Y.....ZN....
0000030: 39b7 373b 0800 4500 004b e269 4000 6006  9.7;..E..K.i@.`.
0000040: 420d 81aa f989 81aa f957 00b3 0016 e976  B........W.....v
0000050: b7d3 1382 8d2f 8018 16d0 e62e 0000 0101  ...../..........
0000060: 080a 000d f1c6 0438 2560 ffff ffff ffff  .......8%`......
0000070: ffff ffff ffff ffff ffff 0017 0200 0221  ...............!
0000080: 21                                       !

Although the loop condition is not seen in the case of silly NLRI prefix
lengths (there is a check for retval < 0), the first updated route is
still printed, resulting in potentially inaccurate reporting, if not
gibberish.

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

*** print-bgp.c Wed Dec 11 02:13:58 2002
--- print-bgp.c.fixed   Sat Dec 14 21:26:07 2002
***************
*** 876,882 ****
                              case SAFNUM_MULTICAST:
                              case SAFNUM_UNIMULTICAST:
                                  advance = decode_prefix4(tptr, buf, sizeof(buf));
!                                 printf("\n\t      %s", buf);
                                  break;
                              case SAFNUM_LABUNICAST:
                                  advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
--- 876,885 ----
                              case SAFNUM_MULTICAST:
                              case SAFNUM_UNIMULTICAST:
                                  advance = decode_prefix4(tptr, buf, sizeof(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,984 ****
                              case SAFNUM_MULTICAST:
                              case SAFNUM_UNIMULTICAST:
                                  advance = decode_prefix4(tptr, buf, sizeof(buf));
!                                 printf("\n\t      %s", buf);
                                  break;
                              case SAFNUM_LABUNICAST:
                                  advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
--- 981,990 ----
                              case SAFNUM_MULTICAST:
                              case SAFNUM_UNIMULTICAST:
                                  advance = decode_prefix4(tptr, buf, sizeof(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,1292 ****
--- 1293,1299 ----
                printf("\n\t  Withdrawn routes: %d bytes", len);
  #else
                char buf[MAXHOSTNAMELEN + 100];
+               int wpfx;
  
                TCHECK2(p[2], len);
                i = 2;
***************
*** 1294,1301 ****
                printf("\n\t  Withdrawn routes:");
  
                while(i < 2 + len) {
!                       i += decode_prefix4(&p[i], buf, sizeof(buf));
!                       printf("\n\t    %s", buf);
                }
  #endif
        }
--- 1301,1314 ----
                printf("\n\t  Withdrawn routes:");
  
                while(i < 2 + len) {
!                       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,1349 ****
                while (dat + length > p) {
                        char buf[MAXHOSTNAMELEN + 100];
                        i = decode_prefix4(p, buf, sizeof(buf));
!                       printf("\n\t    %s", buf);
!                       if (i < 0)
                                break;
!                       p += i;
                }
        }
        return;
--- 1353,1365 ----
                while (dat + length > p) {
                        char buf[MAXHOSTNAMELEN + 100];
                        i = decode_prefix4(p, buf, sizeof(buf));
!                       if (i >= 0) {
!                               printf("\n\t    %s", buf);
!                               p += i;
!                       } else {
!                               printf("\n\t    (illegal prefix length)");
                                break;
!                       }
                }
        }
        return;



-- 
George Bakos
Institute for Security Technology Studies
Dartmouth College
gbakos () ists dartmouth edu
voice   603-646-0665
fax     603-646-0666
Key fingerprint = D646 8F91 F795 27EC FF8B  8C95 B102 9EB2 081E CB85
-
This is the TCPDUMP workers list. It is archived at
http://www.tcpdump.org/lists/workers/index.html
To unsubscribe use mailto:tcpdump-workers-request () tcpdump org?body=unsubscribe


Current thread: