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
