On Sun, Oct 25, 2020 at 12:15:22AM +0200, Jeremie Courreges-Anglas wrote:
> 
> dunno why the strange combination of To/Cc headers so I'll keep bugs@ in Cc:

My answer is inline below:

> On Sat, Oct 24 2020, [email protected] wrote:
> >>Synopsis:   a specially crafted packet can set tcpdump into an endless loop
> >>Category:   system
> >>Environment:
> >     System      : OpenBSD 6.8
> >     Details     : OpenBSD 6.8 (GENERIC.MP) #98: Sun Oct  4 18:13:26 MDT 2020
> >                      
> > [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> >
> >     Architecture: OpenBSD.amd64
> >     Machine     : amd64
> >>Description:
> >     I was (un)fortunate enough to have this treat of a bug from a cracker
> > on the 'net.  Thanks!  They sent me an infinite loop in tcpdump.  I bug 
> > hunted
> > and shared my findings on the misc@ mailing list.  I wasn't sure becuase I'm
> > not the best code reader so I crafted a DOS to exploit this infinite loop.
> > I have mailed OpenBSD off-lists with this proof of concept code.
> >>How-To-Repeat:
> > before patch:
> >
> > tcpdump -v -n -i lo0 port 8888
> >
> > 10:30:54.667969 127.0.0.1.2123 > 127.0.0.1.8888: [udp sum ok]  GTPv1-C 
> > (teid 0, len 0) [MBMS Support] [MBMS Support] [MBMS Support] [MBMS Support] 
> > [MBMS Support] [MBMS Support] [MBMS Support] [MBMS Support] [MBMS Support] 
> > [MBMS Support] [MBMS Support] [MBMS Support] ...
> > 2 packets received by filter
> > 0 packets dropped by kernel
> >
> > This was triggered with netcat:
> >
> > nc -up 2123 localhost 8888 < dos.packet
> >
> >>Fix:
> > after patch:
> >
> > tcpdump.p: listening on lo0, link-type LOOP
> > 10:43:41.005389 127.0.0.1.2123 > 127.0.0.1.8888: [udp sum ok]  GTPv1-C 
> > (teid 0, len 0) [|GTPv1-C] (ttl 64, id 58060, len 41)
> > ^C
> > 2 packets received by filter
> > 0 packets dropped by kernel
> > spica# tcpdump.p -v -n -i lo0 -Xp-sp1500pport88888
> > tcpdump.p: listening on lo0, link-type LOOP
> > 10:44:11.956464 127.0.0.1.2123 > 127.0.0.1.8888: [udp sum ok]  GTPv1-C 
> > (teid 0, len 0) [|GTPv1-C] (ttl 64, id 18693, len 41)
> >   0000: 4500 0029 4905 0000 4011 33bd 7f00 0001      E..)[email protected].....
> >   0010: 7f00 0001 084b 22b8 0015 a2bd 3400 0000      .....K".....4...
> >   0020: 0000 0000 0000 0001 00                       .........
> >
> > ^C
> > 2 packets received by filter
> > 0 packets dropped by kernel
> >
> > The patch looks like follows:
> >
> > Index: print-gtp.c
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/tcpdump/print-gtp.c,v
> > retrieving revision 1.12
> > diff -u -p -u -r1.12 print-gtp.c
> > --- print-gtp.c     20 May 2020 01:20:37 -0000      1.12
> > +++ print-gtp.c     24 Oct 2020 08:56:00 -0000
> > @@ -927,6 +927,8 @@ gtp_v1_print(const u_char *cp, u_int len
> >  
> >                     /* Header length is a 4 octet multiplier. */
> 
> I've never seen GTP in the wild but indeed a length of zero is invalid.
> In case it can help other reviewers:

I was possibly not exploited as a natural DNS packet can trigger this.  And
that's how I found this bug in the first place by tcpdumping DNS.  Consider
this program to create the crafted packet:

beta$ ./bad-packet > evil.2            
beta$ hexdump -C evil.2                
00000000  34 00 00 00 00 01 00 00  00 00 00 02 00 00 00 00  |4...............|
00000010
beta$ vi bad-packet.c                  
beta$ cc -g -o bad-packet bad-packet.c 
beta$ ./bad-packet > evil.2            
beta$ nc -up 2123 127.0.0.1 8888 < evil.2

On the other screen then where I had a tcpdump on port 8888 (pretend it was 53):

rting] [MS Info Change Reporting] [MS Info Change Reporting] [MS Info Change 
Reporting] [MS Info Change Reporting] [MS Info Change Reporting] [MS Info 
Change Reporting] [MS Inf^C
19 packets received by filter

Same scenario only a bit different.  The DNS packet then consists of:

(from RFC 1035)
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      ID                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    QDCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ANCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    NSCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ARCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

an ID=0x3400 (netbyte order)
QDCOUNT of 1    (comes with any answer)
ARCOUNT of 2    (say an OPT and a TSIG payload)

is an answer packet.  Port must be 2123 for the query.

The program to create evil.2 is:

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int
main(void)
{
        char packet[16];

        memset(&packet, 0, sizeof(packet));

        packet[0] = 0x34;

        packet[5] = 1;
        packet[9] = 1;
        packet[11] = 2;

        write(STDOUT_FILENO, packet, sizeof(packet));
}

>   
> https://www.etsi.org/deliver/etsi_ts/129000_129099/129060/15.05.00_60/ts_129060v150500p.pdf
> 
> >                     hlen = (int)p[0] * 4;
> > +                   if (hlen == 0)
> > +                           goto trunc;
> 
> LGTM, though I'd suggest printing why we're bailing out.

What would be a good error message?

Best Regards,

-peter

> 
> Index: print-gtp.c
> ===================================================================
> RCS file: /d/cvs/src/usr.sbin/tcpdump/print-gtp.c,v
> retrieving revision 1.12
> diff -u -p -p -u -r1.12 print-gtp.c
> --- print-gtp.c       20 May 2020 01:20:37 -0000      1.12
> +++ print-gtp.c       24 Oct 2020 22:02:47 -0000
> @@ -927,6 +927,11 @@ gtp_v1_print(const u_char *cp, u_int len
>  
>                       /* Header length is a 4 octet multiplier. */
>                       hlen = (int)p[0] * 4;
> +                     if (hlen == 0) {
> +                             printf(" [Invalid zero-length header %u]",
> +                                 nexthdr);
> +                             goto trunc;
> +                     }
>                       TCHECK2(p[0], hlen);
>  
>                       switch (nexthdr) {
> 
> -- 
> jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply via email to