CVE-2017-13014: Out-of-bounds Read (CWE-125)
value: The White Board protocol parser in tcpdump before 4.9.2 has a buffer over-read in print-wb.c:wb_prep(), several functions.
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-wb.c, tests/TESTLIST, tests/wb-oobr.out
Commit date: 2017-09-13 12:25:44 +0100
Commit message: CVE-2017-13014/White Board: Do more bounds checks.

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

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

While we're at it, print a truncation error if the packets are
truncated, rather than just, in effect, ignoring the result of the
routines that print particular packet types.

Diff: diff --git a/print-wb.c b/print-wb.c
index 88857d9618..c0df48d747 100644
--- a/print-wb.c
+++ b/print-wb.c
@@ -261,13 +261,12 @@ wb_prep(netdissect_options *ndo,
 	int n;
 	const struct pgstate *ps;
 	const u_char *ep = ndo->ndo_snapend;
 
 	ND_PRINT((ndo, " wb-prep:"));
-	if (len < sizeof(*prep)) {
+	if (len < sizeof(*prep) || !ND_TTEST(*prep))
 		return (-1);
-	}
 	n = EXTRACT_32BITS(&prep->pp_n);
 	ps = (const struct pgstate *)(prep + 1);
 	while (--n >= 0 && ND_TTEST(*ps)) {
 		const struct id_off *io, *ie;
 		char c = '<';
@@ -417,35 +416,41 @@ wb_print(netdissect_options *ndo,
 		return;
 
 	case PT_ID:
 		if (wb_id(ndo, (const struct pkt_id *)(ph + 1), len) >= 0)
 			return;
+		ND_PRINT((ndo, "%s", tstr));
 		break;
 
 	case PT_RREQ:
 		if (wb_rreq(ndo, (const struct pkt_rreq *)(ph + 1), len) >= 0)
 			return;
+		ND_PRINT((ndo, "%s", tstr));
 		break;
 
 	case PT_RREP:
 		if (wb_rrep(ndo, (const struct pkt_rrep *)(ph + 1), len) >= 0)
 			return;
+		ND_PRINT((ndo, "%s", tstr));
 		break;
 
 	case PT_DRAWOP:
 		if (wb_drawop(ndo, (const struct pkt_dop *)(ph + 1), len) >= 0)
 			return;
+		ND_PRINT((ndo, "%s", tstr));
 		break;
 
 	case PT_PREQ:
 		if (wb_preq(ndo, (const struct pkt_preq *)(ph + 1), len) >= 0)
 			return;
+		ND_PRINT((ndo, "%s", tstr));
 		break;
 
 	case PT_PREP:
 		if (wb_prep(ndo, (const struct pkt_prep *)(ph + 1), len) >= 0)
 			return;
+		ND_PRINT((ndo, "%s", tstr));
 		break;
 
 	default:
 		ND_PRINT((ndo, " wb-%d!", ph->ph_type));
 		return;
diff --git a/tests/TESTLIST b/tests/TESTLIST
index d69e940513..b16737cf6a 100644
--- a/tests/TESTLIST
+++ b/tests/TESTLIST
@@ -504,10 +504,11 @@ 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
+wb-oobr			wb-oobr.pcap			wb-oobr.out	-v
 
 # bad packets from Bhargava Shastry
 lldp_asan		lldp_asan.pcap			lldp_asan.out	-v
 extract_read2_asan	extract_read2_asan.pcap		extract_read2_asan.out	-v
 getname_2_read4_asan	getname_2_read4_asan.pcap	getname_2_read4_asan.out	-v
diff --git a/tests/wb-oobr.out b/tests/wb-oobr.out
new file mode 100644
index 0000000000..9f00e37d50
--- /dev/null
+++ b/tests/wb-oobr.out
@@ -0,0 +1,18 @@
+MPLS (label 197376, exp 7, [S], ttl 48)
+	IP (tos 0x30, ttl 48, id 12336, offset 0, flags [none], proto UDP (17), length 12336, bad cksum 3030 (->7754)!)
+    48.4.4.4.4400 > 127.0.0.1.3503: 
+		 packet exceeded snapshot
+IP (tos 0x30, ttl 48, id 12336, offset 0, flags [none], proto UDP (17), length 12336, bad cksum 3030 (->699d)!)
+    48.48.48.48.3503 > 48.48.48.48.4567: * wb-prep:[|wb]
+MPLS (label 197376, exp 7, [S], ttl 48)
+	IP (tos 0x30, ttl 48, id 12336, offset 0, flags [none], proto UDP (17), length 12336, bad cksum 3030 (->699d)!)
+    48.48.48.48.4400 > 48.48.48.48.3503: 
+		 packet exceeded snapshot
+IP (tos 0x30, ttl 48, id 12336, offset 0, flags [none], proto UDP (17), length 12336, bad cksum 3030 (->c624)!)
+    48.48.0.1.3503 > 48.4.4.4.4567: * wb-prep:[|wb]
+MPLS (label 197376, exp 7, [S], ttl 48)
+	IP (tos 0x30, ttl 48, id 12336, offset 0, flags [none], proto UDP (17), length 12336, bad cksum 3030 (->7754)!)
+    48.4.4.4.4400 > 127.0.0.1.3503: 
+		 packet exceeded snapshot
+IP (tos 0x30, ttl 48, id 12336, offset 0, flags [none], proto UDP (17), length 12336, bad cksum 3030 (->c624)!)
+    48.48.0.1.3503 > 48.4.4.4.4567: * wb-prep:[|wb]
diff --git a/tests/wb-oobr.pcap b/tests/wb-oobr.pcap
new file mode 100644
index 0000000000..577b1a0f40
Binary files /dev/null and b/tests/wb-oobr.pcap differ

Vulnerable code: 	if (len < sizeof(*prep)) {
	}
Fixed code: 	if (len < sizeof(*prep) || !ND_TTEST(*prep))
		ND_PRINT((ndo, "%s", tstr));
		ND_PRINT((ndo, "%s", tstr));
		ND_PRINT((ndo, "%s", tstr));
		ND_PRINT((ndo, "%s", tstr));
		ND_PRINT((ndo, "%s", tstr));
		ND_PRINT((ndo, "%s", tstr));
wb-oobr			wb-oobr.pcap			wb-oobr.out	-v
MPLS (label 197376, exp 7, [S], ttl 48)
	IP (tos 0x30, ttl 48, id 12336, offset 0, flags [none], proto UDP (17), length 12336, bad cksum 3030 (->7754)!)
    48.4.4.4.4400 > 127.0.0.1.3503: 
		 packet exceeded snapshot
IP (tos 0x30, ttl 48, id 12336, offset 0, flags [none], proto UDP (17), length 12336, bad cksum 3030 (->699d)!)
    48.48.48.48.3503 > 48.48.48.48.4567: * wb-prep:[|wb]
MPLS (label 197376, exp 7, [S], ttl 48)
	IP (tos 0x30, ttl 48, id 12336, offset 0, flags [none], proto UDP (17), length 12336, bad cksum 3030 (->699d)!)
    48.48.48.48.4400 > 48.48.48.48.3503: 
		 packet exceeded snapshot
IP (tos 0x30, ttl 48, id 12336, offset 0, flags [none], proto UDP (17), length 12336, bad cksum 3030 (->c624)!)
    48.48.0.1.3503 > 48.4.4.4.4567: * wb-prep:[|wb]
MPLS (label 197376, exp 7, [S], ttl 48)
	IP (tos 0x30, ttl 48, id 12336, offset 0, flags [none], proto UDP (17), length 12336, bad cksum 3030 (->7754)!)
    48.4.4.4.4400 > 127.0.0.1.3503: 
		 packet exceeded snapshot
IP (tos 0x30, ttl 48, id 12336, offset 0, flags [none], proto UDP (17), length 12336, bad cksum 3030 (->c624)!)
    48.48.0.1.3503 > 48.4.4.4.4567: * wb-prep:[|wb]