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

The IPv6 parser in tcpdump before 4.9.2 has a buffer over-read in print-ip6.c:ip6_print().

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-02-04 03:13:18-08:00
msg: CVE-2017-12985/IPv6: Check for print routines returning -1 when running past the end.

rt6_print(), ah_print(), and esp_print() return -1 if they run up
against the end of the packet while dissecting; if that happens, stop
dissecting, don't try to fetch the next header value, because 1) *it*
might be past the end of the packet and 2) we won't be using it in any
case, as we'll be exiting the loop.

Also, change mobility_print() to return -1 if it runs up against the
end of the packet, and stop dissecting if it does so.

This fixes a buffer over-read discovered by Brian 'geeknik' Carpenter.

Add tests using the capture files 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-ip6.c
change_type: ModificationType.MODIFY
diff: @@ -280,6 +280,8 @@ ip6_print(netdissect_options *ndo, const u_char *bp, u_int length)
 	advance = sizeof(struct ip6_hdr);
 	nh = ip6->ip6_nxt;
 	while (cp < ndo->ndo_snapend && advance > 0) {
+		if (len < (u_int)advance)
+			goto trunc;
 		cp += advance;
 		len -= advance;
 
@@ -322,10 +324,15 @@ ip6_print(netdissect_options *ndo, const u_char *bp, u_int length)
 			 * mobility header.
 			 */
 			advance = mobility_print(ndo, cp, (const u_char *)ip6);
+			if (advance < 0)
+				return;
 			nh = *cp;
 			return;
 		case IPPROTO_ROUTING:
+			ND_TCHECK(*cp);
 			advance = rt6_print(ndo, cp, (const u_char *)ip6);
+			if (advance < 0)
+				return;
 			nh = *cp;
 			break;
 		case IPPROTO_SCTP:
@@ -345,12 +352,16 @@ ip6_print(netdissect_options *ndo, const u_char *bp, u_int length)
 			return;
 		case IPPROTO_AH:
 			advance = ah_print(ndo, cp);
+			if (advance < 0)
+				return;
 			nh = *cp;
 			break;
 		case IPPROTO_ESP:
 		    {
 			int enh, padlen;
 			advance = esp_print(ndo, cp, len, (const u_char *)ip6, &enh, &padlen);
+			if (advance < 0)
+				return;
 			nh = enh & 0xff;
 			len -= padlen;
 			break;

programming_language: C
filename: print-mobility.c
change_type: ModificationType.MODIFY
diff: @@ -332,5 +332,5 @@ mobility_print(netdissect_options *ndo,
 
  trunc:
 	ND_PRINT((ndo, "%s", tstr));
-	return(mhlen);
+	return(-1);
 }

programming_language: C
filename: TESTLIST
change_type: ModificationType.MODIFY
diff: @@ -432,6 +432,8 @@ otv-heapoverflow-1	otv-heapoverflow-1.pcap		otv-heapoverflow-1.out		-c10
 otv-heapoverflow-2	otv-heapoverflow-2.pcap		otv-heapoverflow-2.out		-c10
 q933-heapoverflow-2	q933-heapoverflow-2.pcap	q933-heapoverflow-2.out
 atm-heapoverflow	atm-heapoverflow.pcap		atm-heapoverflow.out		-c1 -e
+ipv6-next-header-oobr-1	ipv6-next-header-oobr-1.pcap	ipv6-next-header-oobr-1.out
+ipv6-next-header-oobr-2	ipv6-next-header-oobr-2.pcap	ipv6-next-header-oobr-2.out
 
 # bad packets from Kamil Frankowicz
 snmp-heapoverflow-1	snmp-heapoverflow-1.pcap	snmp-heapoverflow-1.out

programming_language: Shell
filename: ipv6-next-header-oobr-1.out
change_type: ModificationType.ADD
diff: @@ -0,0 +1 @@
+IP6 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [|ip6]

programming_language: Markdown
filename: ipv6-next-header-oobr-2.out
change_type: ModificationType.ADD
diff: @@ -0,0 +1 @@
+IP6 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [|AH]

programming_language: Markdown