CVE-2017-13039 (Other, published 2017-09-14T06:29Z)
Description: value: The ISAKMP parser in tcpdump before 4.9.2 has a buffer over-read in print-isakmp.c, several functions.
Severity: HIGH (CVSS v3 base score: 9.8)
Weakness: CWE-125 \u2014 Out-of-bounds Read
The product reads data past the end, or before the beginning, of the intended buffer.
Repository: https://github.com/the-tcpdump-group/tcpdump
Files changed:
print-isakmp.c
tests/TESTLIST
tests/isakmpv1-attr-oobr.out
Commit message: CVE-2017-13039/IKEv1: Do more bounds checking.

Have ikev1_attrmap_print() and ikev1_attr_print() do full bounds
checking, and return null on a bounds overflow.  Have their callers
check for a null return.

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), modified
so the capture file won't be rejected as an invalid capture.


Vulnerable code:
		    const u_char *p, const u_char *ep,
	else
	if (ep < p + totlen) {
		return ep + 1;
		else
			rawprint(ndo, (const uint8_t *)&p[2], 2);
		ND_PRINT((ndo,"len=%d value=", EXTRACT_16BITS(&p[2])));
		rawprint(ndo, (const uint8_t *)&p[4], EXTRACT_16BITS(&p[2]));
ikev1_attr_print(netdissect_options *ndo, const u_char *p, const u_char *ep)
	else
	if (ep < p + totlen) {
		return ep + 1;
		rawprint(ndo, (const uint8_t *)&p[2], 2);
		ND_PRINT((ndo,"len=%d value=", EXTRACT_16BITS(&p[2])));
		rawprint(ndo, (const uint8_t *)&p[4], EXTRACT_16BITS(&p[2]));
		if (map && nmap) {
			cp = ikev1_attrmap_print(ndo, cp, (ep < ep2) ? ep : ep2,
				map, nmap);
		} else
			cp = ikev1_attr_print(ndo, cp, (ep < ep2) ? ep : ep2);
				cp = ikev1_attrmap_print(ndo, cp,
					(ep < ep2) ? ep : ep2, map, nmap);
			cp = ikev1_attrmap_print(ndo, cp, (ep < ep2) ? ep : ep2,
				map, nmap);
			cp = ikev1_attr_print(ndo, cp, (ep < ep2) ? ep : ep2);

Fixed code:
		    const u_char *p, const u_char *ep2,
	ND_TCHECK(p[0]);
	else {
		ND_TCHECK_16BITS(&p[2]);
	}
	if (ep2 < p + totlen) {
		return ep2 + 1;
	ND_TCHECK_16BITS(&p[0]);
		ND_TCHECK_16BITS(&p[2]);
		else {
			if (!rawprint(ndo, (const uint8_t *)&p[2], 2)) {
				ND_PRINT((ndo,")"));
				goto trunc;
			}
		}
		ND_PRINT((ndo,"len=%d value=", totlen - 4));
		if (!rawprint(ndo, (const uint8_t *)&p[4], totlen - 4)) {
			ND_PRINT((ndo,")"));
			goto trunc;
		}

trunc:
	return NULL;
ikev1_attr_print(netdissect_options *ndo, const u_char *p, const u_char *ep2)
	ND_TCHECK(p[0]);
	else {
		ND_TCHECK_16BITS(&p[2]);
	}
	if (ep2 < p + totlen) {
		return ep2 + 1;
	ND_TCHECK_16BITS(&p[0]);
		if (!rawprint(ndo, (const uint8_t *)&p[2], 2)) {
			ND_PRINT((ndo,")"));
			goto trunc;
		}
		ND_PRINT((ndo,"len=%d value=", totlen - 4));
		if (!rawprint(ndo, (const uint8_t *)&p[4], totlen - 4)) {
			ND_PRINT((ndo,")"));
			goto trunc;
		}

trunc:
	return NULL;
		if (map && nmap)
			cp = ikev1_attrmap_print(ndo, cp, ep2, map, nmap);
		else
			cp = ikev1_attr_print(ndo, cp, ep2);
		if (cp == NULL)
			goto trunc;
				cp = ikev1_attrmap_print(ndo, cp, ep2, map, nmap);
				if (cp == NULL) {
					ND_PRINT((ndo,")"));
					goto trunc;
				}
			cp = ikev1_attrmap_print(ndo, cp, ep2, map, nmap);
			cp = ikev1_attr_print(ndo, cp, ep2);
		if (cp == NULL)
			goto trunc;
isakmpv1-attr-oobr	isakmpv1-attr-oobr.pcap		isakmpv1-attr-oobr.out	-v
IP (tos 0x60, ttl 254, id 40192, offset 0, flags [+, DF, rsvd], proto UDP (17), length 63264, options (unknown 255 [bad length 18]), bad cksum 8e30 (->f45)!)
    251.73.77.150.32514 > 126.172.128.5.500: isakmp 1.0 msgid 2200af01: phase 2/others ? #40:
    (t: #243 id=241 (type=#9472 len=2 value=0619) [|t]) (len mismatch: isakmp 4293885728/ip 2140)