CVE-2017-13044: 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:dhcpv4_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_dhcpv4data-oobr.out
Commit date: 2017-09-13 12:25:44 +0100
Commit message: CVE-2017-13044/HNCP: add DHCPv4-Data bounds checks

dhcpv4_print() in print-hncp.c had the same bug as dhcpv6_print(), apply
a fix along the same lines.

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 d0c9a3ea63..c0e0064481 100644
--- a/print-hncp.c
+++ b/print-hncp.c
@@ -268,10 +268,12 @@ dhcpv4_print(netdissect_options *ndo,
     const u_char *tlv, *value;
     uint8_t type, optlen;
 
     i = 0;
     while (i < length) {
+        if (i + 2 > length)
+            return -1;
         tlv = cp + i;
         type = (uint8_t)tlv[0];
         optlen = (uint8_t)tlv[1];
         value = tlv + 2;
 
@@ -279,10 +281,12 @@ dhcpv4_print(netdissect_options *ndo,
         for (t = indent; t > 0; t--)
             ND_PRINT((ndo, "\t"));
 
         ND_PRINT((ndo, "%s", tok2str(dh4opt_str, "Unknown", type)));
         ND_PRINT((ndo," (%u)", optlen + 2 ));
+        if (i + 2 + optlen > length)
+            return -1;
 
         switch (type) {
         case DH4OPT_DNS_SERVERS:
         case DH4OPT_NTP_SERVERS: {
             if (optlen < 4 || optlen % 4 != 0) {
diff --git a/tests/TESTLIST b/tests/TESTLIST
index c72f7de6f1..b42ba5b149 100644
--- a/tests/TESTLIST
+++ b/tests/TESTLIST
@@ -558,10 +558,12 @@ isakmpv1-attr-oobr	isakmpv1-attr-oobr.pcap		isakmpv1-attr-oobr.out	-v
 # 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
+# Same comments apply to the case below.
+hncp_dhcpv4data-oobr	hncp_dhcpv4data-oobr.pcap	hncp_dhcpv4data-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_dhcpv4data-oobr.out b/tests/hncp_dhcpv4data-oobr.out
new file mode 100644
index 0000000000..7d558dd9d1
--- /dev/null
+++ b/tests/hncp_dhcpv4data-oobr.out
@@ -0,0 +1,4 @@
+IP truncated-ip - 260 bytes missing! (tos 0x12,ECT(0), ttl 48, id 21323, offset 0, flags [+, DF, rsvd], proto UDP (17), length 296, bad cksum 8e0f (->cd08)!)
+    1.2.7.0.1812 > 128.253.0.96.8231: hncp (268)
+	DHCPv4-Data (6)
+		DNS-server (98) (invalid)
diff --git a/tests/hncp_dhcpv4data-oobr.pcap b/tests/hncp_dhcpv4data-oobr.pcap
new file mode 100644
index 0000000000..fb7c7766ad
Binary files /dev/null and b/tests/hncp_dhcpv4data-oobr.pcap differ

Fixed code:         if (i + 2 > length)
            return -1;
        if (i + 2 + optlen > length)
            return -1;
# Same comments apply to the case below.
hncp_dhcpv4data-oobr	hncp_dhcpv4data-oobr.pcap	hncp_dhcpv4data-oobr.out -v -c1
IP truncated-ip - 260 bytes missing! (tos 0x12,ECT(0), ttl 48, id 21323, offset 0, flags [+, DF, rsvd], proto UDP (17), length 296, bad cksum 8e0f (->cd08)!)
    1.2.7.0.1812 > 128.253.0.96.8231: hncp (268)
	DHCPv4-Data (6)
		DNS-server (98) (invalid)