CVE-2017-12899: Out-of-bounds Read (CWE-125)
value: The DECnet parser in tcpdump before 4.9.2 has a buffer over-read in print-decnet.c:decnet_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-decnet.c, tests/TESTLIST, tests/decnet-oobr.out
Commit date: 2017-09-13 12:25:44 +0100
Commit message: CVE-2017-12899/DECnet: Fix bounds checking.

If we're skipping over padding before the *real* flags, check whether
the real flags are in the captured data before fetching it.  This fixes
a buffer over-read discovered by Kamil Frankowicz.

Note one place where we don't need to do bounds checking as it's already
been done.

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

Diff: diff --git a/print-decnet.c b/print-decnet.c
index 88aa9e3ef..de7de2758 100644
--- a/print-decnet.c
+++ b/print-decnet.c
@@ -540,10 +540,11 @@ decnet_print(netdissect_options *ndo,
 	    ND_TCHECK2(ap[sizeof(short)], padlen);
 	    ap += padlen;
 	    length -= padlen;
 	    caplen -= padlen;
 	    rhp = (const union routehdr *)&(ap[sizeof(short)]);
+	    ND_TCHECK(rhp->rh_short.sh_flags);
 	    mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
 	}
 
 	if (mflags & RMF_FVER) {
 		ND_PRINT((ndo, "future-version-decnet"));
@@ -611,10 +612,11 @@ trunc:
 static int
 print_decnet_ctlmsg(netdissect_options *ndo,
                     register const union routehdr *rhp, u_int length,
                     u_int caplen)
 {
+	/* Our caller has already checked for mflags */
 	int mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags);
 	register const union controlmsg *cmp = (const union controlmsg *)rhp;
 	int src, dst, info, blksize, eco, ueco, hello, other, vers;
 	etheraddr srcea, rtea;
 	int priority;
diff --git a/tests/TESTLIST b/tests/TESTLIST
index 248c53973..5e3ea8d51 100644
--- a/tests/TESTLIST
+++ b/tests/TESTLIST
@@ -442,10 +442,11 @@ stp-v4-length-sigsegv	stp-v4-length-sigsegv.pcap	stp-v4-length-sigsegv.out
 hoobr_pimv1		hoobr_pimv1.pcap		hoobr_pimv1.out
 hoobr_safeputs		hoobr_safeputs.pcap		hoobr_safeputs.out
 isakmp-rfc3948-oobr	isakmp-rfc3948-oobr.pcap	isakmp-rfc3948-oobr.out
 isoclns-oobr		isoclns-oobr.pcap		isoclns-oobr.out
 nfs-attr-oobr		nfs-attr-oobr.pcap		nfs-attr-oobr.out
+decnet-oobr		decnet-oobr.pcap		decnet-oobr.out
 
 # bad packets from Wilfried Kirsch
 slip-bad-direction	slip-bad-direction.pcap		slip-bad-direction.out	-ve
 
 # RTP tests
diff --git a/tests/decnet-oobr.out b/tests/decnet-oobr.out
new file mode 100644
index 000000000..c296076e5
--- /dev/null
+++ b/tests/decnet-oobr.out
@@ -0,0 +1,4 @@
+30:30:30:30:30:30 > 30:30:30:30:30:30, ethertype Unknown (0x3030), length 808464432: 
+	0x0000:  3030 3030 3030 3030 3030 3030 3030 3030  0000000000000000
+	0x0010:  3030 3030                                0000
+MEDSA 16.6:48: [|decnet]
diff --git a/tests/decnet-oobr.pcap b/tests/decnet-oobr.pcap
new file mode 100644
index 000000000..7c09c1ea5
Binary files /dev/null and b/tests/decnet-oobr.pcap differ

Fixed code: 	    ND_TCHECK(rhp->rh_short.sh_flags);
	/* Our caller has already checked for mflags */
decnet-oobr		decnet-oobr.pcap		decnet-oobr.out
30:30:30:30:30:30 > 30:30:30:30:30:30, ethertype Unknown (0x3030), length 808464432: 
	0x0000:  3030 3030 3030 3030 3030 3030 3030 3030  0000000000000000
	0x0010:  3030 3030                                0000
MEDSA 16.6:48: [|decnet]