CVE-2017-13689: Out-of-bounds Read (CWE-125)
value: The IKEv1 parser in tcpdump before 4.9.2 has a buffer over-read in print-isakmp.c:ikev1_id_print().
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 9.8
Published: 2017-09-14T06:29Z
Repository: https://github.com/the-tcpdump-group/tcpdump
Language: Other
Files changed: print-isakmp.c, tests/TESTLIST, tests/ikev1_id_ipv6_addr_subnet-oobr.out
Commit date: 2017-09-13 12:25:44 +0100
Commit message: CVE-2017-13689/IKEv1: Fix addr+subnet length check.

An IPv6 address plus subnet mask is 32 bytes, not 20 bytes.
16 bytes of IPv6 address, 16 bytes of subnet mask.

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).

Diff: diff --git a/print-isakmp.c b/print-isakmp.c
index 013de1c283..fbc6c54203 100644
--- a/print-isakmp.c
+++ b/print-isakmp.c
@@ -1433,12 +1433,12 @@ ikev1_id_print(netdissect_options *ndo, u_char tpay _U_,
 			len = 0;
 			break;
 		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
 		    {
 			const u_char *mask;
-			if (len < 20)
-				ND_PRINT((ndo," len=%d [bad: < 20]", len));
+			if (len < 32)
+				ND_PRINT((ndo," len=%d [bad: < 32]", len));
 			else {
 				mask = (const u_char *)(data + sizeof(struct in6_addr));
 				/*XXX*/
 				ND_PRINT((ndo," len=%d %s/0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", len,
 					  ip6addr_string(ndo, data),
diff --git a/tests/TESTLIST b/tests/TESTLIST
index 7437ce763e..0e70972101 100644
--- a/tests/TESTLIST
+++ b/tests/TESTLIST
@@ -575,10 +575,11 @@ lldp_8023_mtu-oobr	lldp_8023_mtu-oobr.pcap	lldp_8023_mtu-oobr.out	-v -c1
 bgp_vpn_rt-oobr	bgp_vpn_rt-oobr.pcap	bgp_vpn_rt-oobr.out	-v -c1
 cfm_sender_id-oobr	cfm_sender_id-oobr.pcap	cfm_sender_id-oobr.out	-v -c1
 isis-extd-isreach-oobr	isis-extd-isreach-oobr.pcap	isis-extd-isreach-oobr.out -v -c4
 olsr-oobr-1		olsr-oobr-1.pcap		olsr-oobr-1.out	-v
 olsr-oobr-2		olsr-oobr-2.pcap		olsr-oobr-2.out	-v
+ikev1_id_ipv6_addr_subnet-oobr	ikev1_id_ipv6_addr_subnet-oobr.pcap	ikev1_id_ipv6_addr_subnet-oobr.out	-v
 
 # bad packets from Katie Holly
 mlppp-oobr		mlppp-oobr.pcap			mlppp-oobr.out
 
 # bad packets from Kim Gwan Yeong
diff --git a/tests/ikev1_id_ipv6_addr_subnet-oobr.out b/tests/ikev1_id_ipv6_addr_subnet-oobr.out
new file mode 100644
index 0000000000..0662f0043e
--- /dev/null
+++ b/tests/ikev1_id_ipv6_addr_subnet-oobr.out
@@ -0,0 +1,3 @@
+IP (tos 0x0, ttl 100, id 40207, offset 0, flags [+, DF, rsvd], proto UDP (17), length 32808, bad cksum 8e7f (->bc78)!)
+    16.0.128.20.500 > 12.251.0.45.0: isakmp 1.0 msgid 0d101010: phase 2/others ? #16[]:
+    (id: idtype=IPv6net protoid=16 port=4112 len=24 [bad: < 32]) [|#145] (len mismatch: isakmp 4278190080/ip 4856)
diff --git a/tests/ikev1_id_ipv6_addr_subnet-oobr.pcap b/tests/ikev1_id_ipv6_addr_subnet-oobr.pcap
new file mode 100644
index 0000000000..b9cfebd2ec
Binary files /dev/null and b/tests/ikev1_id_ipv6_addr_subnet-oobr.pcap differ

Vulnerable code: 			if (len < 20)
				ND_PRINT((ndo," len=%d [bad: < 20]", len));
Fixed code: 			if (len < 32)
				ND_PRINT((ndo," len=%d [bad: < 32]", len));
ikev1_id_ipv6_addr_subnet-oobr	ikev1_id_ipv6_addr_subnet-oobr.pcap	ikev1_id_ipv6_addr_subnet-oobr.out	-v
IP (tos 0x0, ttl 100, id 40207, offset 0, flags [+, DF, rsvd], proto UDP (17), length 32808, bad cksum 8e7f (->bc78)!)
    16.0.128.20.500 > 12.251.0.45.0: isakmp 1.0 msgid 0d101010: phase 2/others ? #16[]:
    (id: idtype=IPv6net protoid=16 port=4112 len=24 [bad: < 32]) [|#145] (len mismatch: isakmp 4278190080/ip 4856)