CVE-2017-13007: Out-of-bounds Read (CWE-125)
value: The Apple PKTAP parser in tcpdump before 4.9.2 has a buffer over-read in print-pktap.c:pktap_if_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-pktap.c, tests/TESTLIST, tests/pktap-heap-overflow.out
Commit date: 2017-09-13 12:25:44 +0100
Commit message: CVE-2017-13007/PKTAP: Pass a properly updated struct pcap_pkthdr to the sub-dissector.

The sub-dissector expects that the length and captured length will
reflect the actual remaining data in the packet, not the raw amount
including the PKTAP header; pass an updated header, just as we do for
PPI.

This fixes a buffer over-read discovered by Yannick Formaggio.

Add a test using the capture file supplied by the reporter(s).

Diff: diff --git a/print-pktap.c b/print-pktap.c
index 7144f3c6e..4a295fdf6 100644
--- a/print-pktap.c
+++ b/print-pktap.c
@@ -102,10 +102,11 @@ pktap_if_print(netdissect_options *ndo,
 	uint32_t dlt, hdrlen, rectype;
 	u_int caplen = h->caplen;
 	u_int length = h->len;
 	if_printer printer;
 	const pktap_header_t *hdr;
+	struct pcap_pkthdr nhdr;
 
 	if (caplen < sizeof(pktap_header_t) || length < sizeof(pktap_header_t)) {
 		ND_PRINT((ndo, "[|pktap]"));
 		return (0);
 	}
@@ -142,11 +143,14 @@ pktap_if_print(netdissect_options *ndo,
 		ND_PRINT((ndo, "no data"));
 		break;
 
 	case PKT_REC_PACKET:
 		if ((printer = lookup_printer(dlt)) != NULL) {
-			hdrlen += printer(ndo, h, p);
+			nhdr = *h;
+			nhdr.caplen = caplen;
+			nhdr.len = length;
+			hdrlen += printer(ndo, &nhdr, p);
 		} else {
 			if (!ndo->ndo_eflag)
 				pktap_header_print(ndo, (const u_char *)hdr,
 						length + hdrlen);
 
diff --git a/tests/TESTLIST b/tests/TESTLIST
index f9ae40dda..5f18a0574 100644
--- a/tests/TESTLIST
+++ b/tests/TESTLIST
@@ -500,10 +500,11 @@ lmpv1_busyloop		lmpv1_busyloop.pcap		lmpv1_busyloop.out	-vvv -e
 juniper_atm1		juniper_atm1.pcap		juniper_atm1.out	-vvv -e
 juniper_es		juniper_es.pcap			juniper_es.out	-vvv -e
 
 # bad packets from Yannick Formaggio
 l2tp-avp-overflow	l2tp-avp-overflow.pcap		l2tp-avp-overflow.out	-v
+pktap-heap-overflow	pktap-heap-overflow.pcap	pktap-heap-overflow.out	-v
 
 # RTP tests
 # fuzzed pcap
 rtp-seg-fault-1  rtp-seg-fault-1.pcap  rtp-seg-fault-1.out  -v -T rtp
 rtp-seg-fault-2  rtp-seg-fault-2.pcap  rtp-seg-fault-2.out  -v -T rtp
diff --git a/tests/pktap-heap-overflow.out b/tests/pktap-heap-overflow.out
new file mode 100644
index 000000000..e23ed9193
--- /dev/null
+++ b/tests/pktap-heap-overflow.out
@@ -0,0 +1,3 @@
+[|pktap]
+[|ppp]
+EXIT CODE 00000100
diff --git a/tests/pktap-heap-overflow.pcap b/tests/pktap-heap-overflow.pcap
new file mode 100644
index 000000000..e8b0f216f
Binary files /dev/null and b/tests/pktap-heap-overflow.pcap differ

Vulnerable code: 			hdrlen += printer(ndo, h, p);
Fixed code: 	struct pcap_pkthdr nhdr;
			nhdr = *h;
			nhdr.caplen = caplen;
			nhdr.len = length;
			hdrlen += printer(ndo, &nhdr, p);
pktap-heap-overflow	pktap-heap-overflow.pcap	pktap-heap-overflow.out	-v
[|pktap]
[|ppp]
EXIT CODE 00000100