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

The IP parser in tcpdump before 4.9.2 has a buffer over-read in print-ip.c:ip_printroute().

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.0/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-03-21 23:07:17-07:00
msg: CVE-2017-13022/IP: Add bounds checks to ip_printroute().

This fixes a buffer over-read discovered by Bhargava Shastry,
SecT/TU Berlin.

Add a test using the capture file supplied by the reporter(s), modified
so the capture file won't be rejected as an invalid capture.
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-ip.c
change_type: ModificationType.MODIFY
diff: @@ -54,7 +54,7 @@ static const struct tok ip_option_values[] = {
 /*
  * print the recorded route in an IP RR, LSRR or SSRR option.
  */
-static void
+static int
 ip_printroute(netdissect_options *ndo,
               register const u_char *cp, u_int length)
 {
@@ -63,19 +63,25 @@ ip_printroute(netdissect_options *ndo,
 
 	if (length < 3) {
 		ND_PRINT((ndo, " [bad length %u]", length));
-		return;
+		return (0);
 	}
 	if ((length + 1) & 3)
 		ND_PRINT((ndo, " [bad length %u]", length));
+	ND_TCHECK(cp[2]);
 	ptr = cp[2] - 1;
 	if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
 		ND_PRINT((ndo, " [bad ptr %u]", cp[2]));
 
 	for (len = 3; len < length; len += 4) {
+		ND_TCHECK2(cp[len], 4);
 		ND_PRINT((ndo, " %s", ipaddr_string(ndo, &cp[len])));
 		if (ptr > len)
 			ND_PRINT((ndo, ","));
 	}
+	return (0);
+
+trunc:
+	return (-1);
 }
 
 /*
@@ -278,7 +284,8 @@ ip_optprint(netdissect_options *ndo,
 		case IPOPT_RR:       /* fall through */
 		case IPOPT_SSRR:
 		case IPOPT_LSRR:
-			ip_printroute(ndo, cp, option_len);
+			if (ip_printroute(ndo, cp, option_len) == -1)
+				goto trunc;
 			break;
 
 		case IPOPT_RA:

programming_language: C
filename: TESTLIST
change_type: ModificationType.MODIFY
diff: @@ -523,6 +523,7 @@ pgm_opts_asan		pgm_opts_asan.pcap		pgm_opts_asan.out	-v
 pgm_opts_asan_2		pgm_opts_asan_2.pcap		pgm_opts_asan_2.out	-v
 vtp_asan		vtp_asan.pcap			vtp_asan.out	-v
 icmp6_mobileprefix_asan	icmp6_mobileprefix_asan.pcap	icmp6_mobileprefix_asan.out	-v
+ip_printroute_asan	ip_printroute_asan.pcap		ip_printroute_asan.out	-v
 
 # RTP tests
 # fuzzed pcap

programming_language: Shell
filename: ip_printroute_asan.out
change_type: ModificationType.ADD
diff: @@ -0,0 +1,2 @@
+IP (tos 0x0, ttl 254, id 25615, offset 65480, flags [DF, rsvd], proto UDP (17), length 32768, options (LSRR [bad length 25] [bad ptr 15] 103.103.103.0, 0.172.0.116, 0.16.36.36, 16.0.36.2 14.9.36.4[|ip]))
+    251.73.86.0 > 0.172.128.5: ip-proto-17

programming_language: Batchfile