CVE-2017-12902 (published 2017-09-14T06:29Z)

The Zephyr parser in tcpdump before 4.9.2 has a buffer over-read in print-zephyr.c, several functions.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-125
cwe_name: Out-of-bounds Read
description: The product reads data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         

Fix information:
repo_url: https://github.com/the-tcpdump-group/tcpdump
commit_details: repo_url: https://github.com/the-tcpdump-group/tcpdump
author: Guy Harris
author_date: 2017-02-04 18:38:47-08:00
msg: CVE-2017-12902/Zephyr: Fix bounds checking.

Use ND_TTEST() rather than comparing against ndo->ndo_snapend ourselves;
it's easy to get the tests wrong.

Check for running out of packet data before checking for running out of
captured data, and distinguish between running out of packet data (which
might just mean "no more strings") and running out of captured data
(which means "truncated").

This fixes a buffer over-read discovered by Forcepoint's security
researchers Otto Airamo & Antti Levomäki.

Add a test using the capture file supplied by the reporter(s).
repository: repo_url: https://github.com/the-tcpdump-group/tcpdump
repo_name: the-tcpdump-group/tcpdump
description: the TCPdump network dissector
repo_language: C
owner: the-tcpdump-group
file_changes: filename: print-zephyr.c
change_type: ModificationType.MODIFY
diff: @@ -83,24 +83,34 @@ static const struct tok z_types[] = {
 static char z_buf[256];
 
 static const char *
-parse_field(netdissect_options *ndo, const char **pptr, int *len)
+parse_field(netdissect_options *ndo, const char **pptr, int *len, int *truncated)
 {
     const char *s;
 
-    if (*len <= 0 || !pptr || !*pptr)
-	return NULL;
-    if (*pptr > (const char *) ndo->ndo_snapend)
-	return NULL;
-
+    /* Start of string */
     s = *pptr;
-    while (*pptr <= (const char *) ndo->ndo_snapend && *len >= 0 && **pptr) {
+    /* Scan for the NUL terminator */
+    for (;;) {
+	if (*len == 0) {
+	    /* Ran out of packet data without finding it */
+	    return NULL;
+	}
+	if (!ND_TTEST(**pptr)) {
+	    /* Ran out of captured data without finding it */
+	    *truncated = 1;
+	    return NULL;
+	}
+	if (**pptr == '\0') {
+	    /* Found it */
+	    break;
+	}
+	/* Keep scanning */
 	(*pptr)++;
 	(*len)--;
     }
+    /* Skip the NUL terminator */
     (*pptr)++;
     (*len)--;
-    if (*len < 0 || *pptr > (const char *) ndo->ndo_snapend)
-	return NULL;
     return s;
 }
 
@@ -139,6 +149,7 @@ zephyr_print(netdissect_options *ndo, const u_char *cp, int length)
     int parselen = length;
     const char *s;
     int lose = 0;
+    int truncated = 0;
 
     /* squelch compiler warnings */
 
@@ -149,8 +160,9 @@ zephyr_print(netdissect_options *ndo, const u_char *cp, int length)
     z.sender = 0;
     z.recipient = 0;
 
-#define PARSE_STRING				\
-	s = parse_field(ndo, &parse, &parselen);	\
+#define PARSE_STRING						\
+	s = parse_field(ndo, &parse, &parselen, &truncated);	\
+	if (truncated) goto trunc;				\
 	if (!s) lose = 1;
 
 #define PARSE_FIELD_INT(field)			\
@@ -183,10 +195,8 @@ zephyr_print(netdissect_options *ndo, const u_char *cp, int length)
     PARSE_FIELD_INT(z.multi);
     PARSE_FIELD_STR(z.multi_uid);
 
-    if (lose) {
-	ND_PRINT((ndo, " [|zephyr] (%d)", length));
-	return;
-    }
+    if (lose)
+        goto trunc;
 
     ND_PRINT((ndo, " zephyr"));
     if (strncmp(z.version+4, "0.2", 3)) {
@@ -318,4 +328,9 @@ zephyr_print(netdissect_options *ndo, const u_char *cp, int length)
     ND_PRINT((ndo, " to %s", z_triple(z.class, z.inst, z.recipient)));
     if (*z.opcode)
 	ND_PRINT((ndo, " op %s", z.opcode));
+    return;
+
+trunc:
+    ND_PRINT((ndo, " [|zephyr] (%d)", length));
+    return;
 }

programming_language: C
filename: TESTLIST
change_type: ModificationType.MODIFY
diff: @@ -462,6 +462,7 @@ icmp-cksum-oobr-4	icmp-cksum-oobr-4.pcap		icmp-cksum-oobr-4.out	-vvv -e
 tok2str-oobr-1		tok2str-oobr-1.pcap		tok2str-oobr-1.out	-vvv -e
 tok2str-oobr-2		tok2str-oobr-2.pcap		tok2str-oobr-2.out	-vvv -e
 eigrp-tlv-oobr		eigrp-tlv-oobr.pcap		eigrp-tlv-oobr.out	-vvv -e
+zephyr-oobr		zephyr-oobr.pcap		zephyr-oobr.out		-vvv -e
 
 # RTP tests
 # fuzzed pcap

programming_language: Shell
filename: zephyr-oobr.out
change_type: ModificationType.ADD
diff: @@ -0,0 +1,2 @@
+00:16:ca:92:12:01 > 00:15:e8:97:b2:01, ethertype IPv4 (0x0800), length 65535: (tos 0x0, ttl 124, id 16059, offset 0, flags [none], proto UDP (17), length 65521)
+    167.155.6.190.2104 > 167.155.9.153.514: [udp sum ok] 

programming_language: Batchfile
repo_url: https://github.com/the-tcpdump-group/tcpdump
commit_details: repo_url: https://github.com/the-tcpdump-group/tcpdump
author: Guy Harris
author_date: 2017-02-07 10:55:59-08:00
msg: CVE-2017-12902/Zephyr: Add an additional test.

File from Kamil Frankowicz.
repository: repo_url: https://github.com/the-tcpdump-group/tcpdump
repo_name: the-tcpdump-group/tcpdump
description: the TCPdump network dissector
repo_language: C
owner: the-tcpdump-group
file_changes: filename: TESTLIST
change_type: ModificationType.MODIFY
diff: @@ -454,6 +454,7 @@ hoobr_ripng_print	hoobr_ripng_print.pcap		hoobr_ripng_print.out
 hoobr_juniper		hoobr_juniper.pcap		hoobr_juniper.out
 hoobr_juniper2		hoobr_juniper2.pcap		hoobr_juniper2.out
 hoobr_juniper3		hoobr_juniper3.pcap		hoobr_juniper3.out
+hoobr_parse_field	hoobr_parse_field.pcap		hoobr_parse_field.out
 
 # bad packets from Wilfried Kirsch
 slip-bad-direction	slip-bad-direction.pcap		slip-bad-direction.out	-ve

programming_language: Shell
filename: hoobr_parse_field.out
change_type: ModificationType.ADD
diff: @@ -0,0 +1,5 @@
+30:30:30:30:30:30 > 30:30:30:30:30:30, ethertype Unknown (0x3030), length 808464432: 
+	0x0000:  3030 3030 3030 3030 3030 3030 3030 3030  0000000000000000
+	0x0010:  3030 3030 3030 3030 3030 3030 3030 3030  0000000000000000
+	0x0020:  3030                                     00
+IP 48.48.48.48.2104 > 48.48.48.48.12336:  [|zephyr] (12308)

programming_language: Shell