CVE-2017-13042: Out-of-bounds Read (CWE-125)
value: The HNCP parser in tcpdump before 4.9.2 has a buffer over-read in print-hncp.c:dhcpv6_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-hncp.c, tests/TESTLIST, tests/hncp_dhcpv6data-oobr.out
Commit date: 2017-09-13 12:25:44 +0100
Commit message: CVE-2017-13042/HNCP: add DHCPv6-Data bounds checks

hncp_print_rec() validates each HNCP TLV to be within the declared as
well as the on-the-wire packet space. However, dhcpv6_print() in the same
file didn't do the same for the DHCPv6 options within the HNCP
DHCPv6-Data TLV value, which could cause an out-of-bounds read when
decoding an invalid packet. Add missing checks to dhcpv6_print().

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-hncp.c b/print-hncp.c
index 32adafa9c0..d0c9a3ea63 100644
--- a/print-hncp.c
+++ b/print-hncp.c
@@ -316,10 +316,12 @@ dhcpv6_print(netdissect_options *ndo,
     const u_char *tlv, *value;
     uint16_t type, optlen;
 
     i = 0;
     while (i < length) {
+        if (i + 4 > length)
+            return -1;
         tlv = cp + i;
         type = EXTRACT_16BITS(tlv);
         optlen = EXTRACT_16BITS(tlv + 2);
         value = tlv + 4;
 
@@ -327,10 +329,12 @@ dhcpv6_print(netdissect_options *ndo,
         for (t = indent; t > 0; t--)
             ND_PRINT((ndo, "\t"));
 
         ND_PRINT((ndo, "%s", tok2str(dh6opt_str, "Unknown", type)));
         ND_PRINT((ndo," (%u)", optlen + 4 ));
+        if (i + 4 + optlen > length)
+            return -1;
 
         switch (type) {
             case DH6OPT_DNS_SERVERS:
             case DH6OPT_SNTP_SERVERS: {
                 if (optlen % 16 != 0) {
diff --git a/tests/TESTLIST b/tests/TESTLIST
index a8811bc696..c72f7de6f1 100644
--- a/tests/TESTLIST
+++ b/tests/TESTLIST
@@ -552,10 +552,16 @@ pim_header_asan-4	pim_header_asan-4.pcap		pim_header_asan-4.out	-v
 ip6_frag_asan		ip6_frag_asan.pcap		ip6_frag_asan.out	-v
 radius_attr_asan	radius_attr_asan.pcap		radius_attr_asan.out	-v
 ospf6_decode_v3_asan	ospf6_decode_v3_asan.pcap	ospf6_decode_v3_asan.out -v
 ip_ts_opts_asan		ip_ts_opts_asan.pcap		ip_ts_opts_asan.out	-v
 isakmpv1-attr-oobr	isakmpv1-attr-oobr.pcap		isakmpv1-attr-oobr.out	-v
+# The case below depends on the bug in print-hncp.c, which at the time of
+# discovery had codepoints for DHCPv6-Data and DHCPv4-Data swapped around.
+# After the bugfix the output will be different because of the different
+# code path and will not test the vulnerability unless modified respectively.
+# The .pcap file is truncated after the 1st packet.
+hncp_dhcpv6data-oobr	hncp_dhcpv6data-oobr.pcap	hncp_dhcpv6data-oobr.out -v -c1
 
 # bad packets from Katie Holly
 mlppp-oobr		mlppp-oobr.pcap			mlppp-oobr.out
 
 # bad packets from Kim Gwan Yeong
diff --git a/tests/hncp_dhcpv6data-oobr.out b/tests/hncp_dhcpv6data-oobr.out
new file mode 100644
index 0000000000..376502d905
--- /dev/null
+++ b/tests/hncp_dhcpv6data-oobr.out
@@ -0,0 +1,7 @@
+IP6 (flowlabel 0x01cc3, hlim 234, next-header UDP (17) payload length: 11025) 400::e4ff:ffff:adf9:8900:0.1646 > 62:9de3:ff47:ebec:8206:ff00:ad:ff00.8231: hncp (11017)
+	Future use: type=16384 (5)
+	DHCPv6-Data (25)
+		Unknown (4)
+		Unknown (4)
+		SNTP-servers (61956)  (invalid)
+	[|hncp]
diff --git a/tests/hncp_dhcpv6data-oobr.pcap b/tests/hncp_dhcpv6data-oobr.pcap
new file mode 100644
index 0000000000..3430e9a858
Binary files /dev/null and b/tests/hncp_dhcpv6data-oobr.pcap differ

Fixed code:         if (i + 4 > length)
            return -1;
        if (i + 4 + optlen > length)
            return -1;
# The case below depends on the bug in print-hncp.c, which at the time of
# discovery had codepoints for DHCPv6-Data and DHCPv4-Data swapped around.
# After the bugfix the output will be different because of the different
# code path and will not test the vulnerability unless modified respectively.
# The .pcap file is truncated after the 1st packet.
hncp_dhcpv6data-oobr	hncp_dhcpv6data-oobr.pcap	hncp_dhcpv6data-oobr.out -v -c1
IP6 (flowlabel 0x01cc3, hlim 234, next-header UDP (17) payload length: 11025) 400::e4ff:ffff:adf9:8900:0.1646 > 62:9de3:ff47:ebec:8206:ff00:ad:ff00.8231: hncp (11017)
	Future use: type=16384 (5)
	DHCPv6-Data (25)
		Unknown (4)
		Unknown (4)
		SNTP-servers (61956)  (invalid)
	[|hncp]