CVE-2017-13016: Out-of-bounds Read (CWE-125)
value: The ISO ES-IS parser in tcpdump before 4.9.2 has a buffer over-read in print-isoclns.c:esis_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: addrtoname.h, print-isoclns.c, tests/TESTLIST, tests/esis_snpa_asan-2.out, tests/esis_snpa_asan-3.out, tests/esis_snpa_asan-4.out, tests/esis_snpa_asan-5.out, tests/esis_snpa_asan.out
Commit date: 2017-09-13 12:25:44 +0100
Commit message: CVE-2017-13016/ES-IS: Fix printing of addresses in RD PDUs.

Always print the SNPA, and flag it as such; only print it as a MAC
address if it's 6 bytes long.

Identify the NET as such.

This fixes a buffer over-read discovered by Bhargava Shastry,
SecT/TU Berlin.

Add tests using the capture files supplied by the reporter(s), modified
so the capture files won't be rejected as an invalid capture.

Diff: diff --git a/addrtoname.h b/addrtoname.h
index 72e5ef19d5..fe8b6bbe54 100644
--- a/addrtoname.h
+++ b/addrtoname.h
@@ -31,11 +31,12 @@
 
 enum {
     LINKADDR_ETHER,
     LINKADDR_FRELAY,
     LINKADDR_IEEE1394,
-    LINKADDR_ATM
+    LINKADDR_ATM,
+    LINKADDR_OTHER
 };
 
 #define BUFSIZE 128
 
 extern const char *linkaddr_string(netdissect_options *, const u_char *, const unsigned int, const unsigned int);
diff --git a/print-isoclns.c b/print-isoclns.c
index 1f871603a4..38c24d9593 100644
--- a/print-isoclns.c
+++ b/print-isoclns.c
@@ -1215,14 +1215,22 @@ esis_print(netdissect_options *ndo,
 		}
 		neta = pptr;
 		pptr += netal;
                 li -= netal;
 
-		if (netal == 0)
-			ND_PRINT((ndo, "\n\t  %s", etheraddr_string(ndo, snpa)));
+		if (snpal == 6)
+			ND_PRINT((ndo, "\n\t  SNPA (length: %u): %s",
+			       snpal,
+			       etheraddr_string(ndo, snpa)));
 		else
-			ND_PRINT((ndo, "\n\t  %s", isonsap_string(ndo, neta, netal)));
+			ND_PRINT((ndo, "\n\t  SNPA (length: %u): %s",
+			       snpal,
+			       linkaddr_string(ndo, snpa, LINKADDR_OTHER, snpal)));
+		if (netal != 0)
+			ND_PRINT((ndo, "\n\t  NET (length: %u) %s",
+			       netal,
+			       isonsap_string(ndo, neta, netal)));
 		break;
 	}
 
 	case ESIS_PDU_ESH:
             ND_TCHECK(*pptr);
diff --git a/tests/TESTLIST b/tests/TESTLIST
index a20e59898f..a56c3c9500 100644
--- a/tests/TESTLIST
+++ b/tests/TESTLIST
@@ -511,10 +511,15 @@ 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
 eap_extract_read2_asan	eap_extract_read2_asan.pcap	eap_extract_read2_asan.out	-v
+esis_snpa_asan		esis_snpa_asan.pcap		esis_snpa_asan.out	-v
+esis_snpa_asan-2	esis_snpa_asan-2.pcap		esis_snpa_asan-2.out	-v
+esis_snpa_asan-3	esis_snpa_asan-3.pcap		esis_snpa_asan-3.out	-v
+esis_snpa_asan-4	esis_snpa_asan-4.pcap		esis_snpa_asan-4.out	-v
+esis_snpa_asan-5	esis_snpa_asan-5.pcap		esis_snpa_asan-5.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/esis_snpa_asan-2.out b/tests/esis_snpa_asan-2.out
new file mode 100644
index 0000000000..0e1dd70015
--- /dev/null
+++ b/tests/esis_snpa_asan-2.out
@@ -0,0 +1,4 @@
+UI 22! ES-IS, length 65565
+	redirect (6), v: 1, checksum: 0x70a1 (incorrect should be 0xf519), holding time: 22339s, length indicator: 17
+	  00.22
+	  SNPA (length: 0): <empty>, opt (0) too long
diff --git a/tests/esis_snpa_asan-2.pcap b/tests/esis_snpa_asan-2.pcap
new file mode 100644
index 0000000000..5c59fa76b6
Binary files /dev/null and b/tests/esis_snpa_asan-2.pcap differ
diff --git a/tests/esis_snpa_asan-3.out b/tests/esis_snpa_asan-3.out
new file mode 100644
index 0000000000..5e6a14d1dc
--- /dev/null
+++ b/tests/esis_snpa_asan-3.out
@@ -0,0 +1,7 @@
+UI 22! ES-IS, length 65565
+	unknown type: 0 (0), v: 1, checksum: 0x00a1 (incorrect should be 0x859d), holding time: 0s, length indicator: 17
+	  0x0000:  0200 04ec ff00 0000
+UI 22! ES-IS, length 2650865693
+	redirect (6), v: 1, checksum: 0x0300 (incorrect should be 0xbce5), holding time: 21480s, length indicator: 17
+	  ec.ff00.00
+	  SNPA (length: 0): <empty>
diff --git a/tests/esis_snpa_asan-3.pcap b/tests/esis_snpa_asan-3.pcap
new file mode 100644
index 0000000000..812f54290f
Binary files /dev/null and b/tests/esis_snpa_asan-3.pcap differ
diff --git a/tests/esis_snpa_asan-4.out b/tests/esis_snpa_asan-4.out
new file mode 100644
index 0000000000..249b248bf8
--- /dev/null
+++ b/tests/esis_snpa_asan-4.out
@@ -0,0 +1,21 @@
+UI 22! ES-IS, length 65565
+	ESH (2), v: 1, checksum: 0x70a1 (incorrect should be 0xfb4e), holding time: 21315s, length indicator: 17
+	  Number of Source Addresses: 2
+	  NET (length: 0): isonsap_string: illegal length
+	  NET (length: 4): ec.ff00.00, bad opts/li
+UI 22! ES-IS, length 65565
+	redirect (6), v: 1, checksum: 0x7034 (incorrect should be 0x44ec), holding time: 21315s, length indicator: 16
+	  02.0400
+	  SNPA (length: 0): <empty>
+	  Unknown Option #0, length 0, value: 
+UI 32! ES-IS, length 65565
+	ESH (2), v: 1, checksum: 0x70a1 (incorrect should be 0xfb4e), holding time: 21315s, length indicator: 17
+	  Number of Source Addresses: 2
+	  NET (length: 0): isonsap_string: illegal length
+	  NET (length: 4): ec.ff00.00, bad opts/li
+UI 22! ES-IS, length 4244701213
+	redirect (6), v: 1, checksum: 0x7034 (incorrect should be 0x36fe), holding time: 21315s, length indicator: 17
+	  isonsap_string: illegal length
+	  SNPA (length: 0): <empty>
+	  NET (length: 4) 00.0000.00
+Q.922, invalid address
diff --git a/tests/esis_snpa_asan-4.pcap b/tests/esis_snpa_asan-4.pcap
new file mode 100644
index 0000000000..9cdfe03476
Binary files /dev/null and b/tests/esis_snpa_asan-4.pcap differ
diff --git a/tests/esis_snpa_asan-5.out b/tests/esis_snpa_asan-5.out
new file mode 100644
index 0000000000..bd8c30dd2a
--- /dev/null
+++ b/tests/esis_snpa_asan-5.out
@@ -0,0 +1,10 @@
+UI 22! ES-IS, length 65565
+	ESH (2), v: 1, checksum: 0x70a1 (incorrect should be 0xfc4c), holding time: 21315s, length indicator: 17
+	  Number of Source Addresses: 3
+	  NET (length: 0): isonsap_string: illegal length
+	  NET (length: 4): ec.ff00.00
+	  NET (length: 0): isonsap_string: illegal length
+UI 22! ES-IS, length 65565
+	redirect (6), v: 1, checksum: 0x7034 (incorrect should be 0x3ff0), holding time: 21315s, length indicator: 17
+	  04
+	  SNPA (length: 4): 00:00:00:00, bad opts/li
diff --git a/tests/esis_snpa_asan-5.pcap b/tests/esis_snpa_asan-5.pcap
new file mode 100644
index 0000000000..98e34f1621
Binary files /dev/null and b/tests/esis_snpa_asan-5.pcap differ
diff --git a/tests/esis_snpa_asan.out b/tests/esis_snpa_asan.out
new file mode 100644
index 0000000000..82732ca06a
--- /dev/null
+++ b/tests/esis_snpa_asan.out
@@ -0,0 +1,12 @@
+UI 22! ES-IS, length 65565
+	ESH (2), v: 1, checksum: 0x70a1 (incorrect should be 0xfb4e), holding time: 21315s, length indicator: 17
+	  Number of Source Addresses: 2
+	  NET (length: 0): isonsap_string: illegal length
+	  NET (length: 4): ec.ff00.00, bad opts/li
+UI 22! ES-IS, length 65565
+	redirect (6), v: 1, checksum: 0xffff (incorrect should be 0x6b16), holding time: 21253s, length indicator: 17
+	  00.04ec.0000
+	  SNPA (length: 0): <empty>, bad opts/li
+Q.922, hdr-len 2, DLCI 0, Flags [FECN], NLPID unknown (0x22), length 72482: 
+	0x0000:  0082 1000 5542 5343 70a1 0200 0400 0000  ....UBSCp.......
+	0x0010:  007e                                     .~
diff --git a/tests/esis_snpa_asan.pcap b/tests/esis_snpa_asan.pcap
new file mode 100644
index 0000000000..b573467cb1
Binary files /dev/null and b/tests/esis_snpa_asan.pcap differ

Vulnerable code:     LINKADDR_ATM
		if (netal == 0)
			ND_PRINT((ndo, "\n\t  %s", etheraddr_string(ndo, snpa)));
			ND_PRINT((ndo, "\n\t  %s", isonsap_string(ndo, neta, netal)));
Fixed code:     LINKADDR_ATM,
    LINKADDR_OTHER
		if (snpal == 6)
			ND_PRINT((ndo, "\n\t  SNPA (length: %u): %s",
			       snpal,
			       etheraddr_string(ndo, snpa)));
			ND_PRINT((ndo, "\n\t  SNPA (length: %u): %s",
			       snpal,
			       linkaddr_string(ndo, snpa, LINKADDR_OTHER, snpal)));
		if (netal != 0)
			ND_PRINT((ndo, "\n\t  NET (length: %u) %s",
			       netal,
			       isonsap_string(ndo, neta, netal)));
esis_snpa_asan		esis_snpa_asan.pcap		esis_snpa_asan.out	-v
esis_snpa_asan-2	esis_snpa_asan-2.pcap		esis_snpa_asan-2.out	-v
esis_snpa_asan-3	esis_snpa_asan-3.pcap		esis_snpa_asan-3.out	-v
esis_snpa_asan-4	esis_snpa_asan-4.pcap		esis_snpa_asan-4.out	-v
esis_snpa_asan-5	esis_snpa_asan-5.pcap		esis_snpa_asan-5.out	-v
UI 22! ES-IS, length 65565
	redirect (6), v: 1, checksum: 0x70a1 (incorrect should be 0xf519), holding time: 22339s, length indicator: 17
	  00.22
	  SNPA (length: 0): <empty>, opt (0) too long
UI 22! ES-IS, length 65565
	unknown type: 0 (0), v: 1, checksum: 0x00a1 (incorrect should be 0x859d), holding time: 0s, length indicator: 17
	  0x0000:  0200 04ec ff00 0000
UI 22! ES-IS, length 2650865693
	redirect (6), v: 1, checksum: 0x0300 (incorrect should be 0xbce5), holding time: 21480s, length indicator: 17
	  ec.ff00.00
	  SNPA (length: 0): <empty>
UI 22! ES-IS, length 65565
	ESH (2), v: 1, checksum: 0x70a1 (incorrect should be 0xfb4e), holding time: 21315s, length indicator: 17
	  Number of Source Addresses: 2
	  NET (length: 0): isonsap_string: illegal length
	  NET (length: 4): ec.ff00.00, bad opts/li
UI 22! ES-IS, length 65565
	redirect (6), v: 1, checksum: 0x7034 (incorrect should be 0x44ec), holding time: 21315s, length indicator: 16
	  02.0400
	  SNPA (length: 0): <empty>
	  Unknown Option #0, length 0, value: 
UI 32! ES-IS, length 65565
	ESH (2), v: 1, checksum: 0x70a1 (incorrect should be 0xfb4e), holding time: 21315s, length indicator: 17
	  Number of Source Addresses: 2
	  NET (length: 0): isonsap_string: illegal length
	  NET (length: 4): ec.ff00.00, bad opts/li
UI 22! ES-IS, length 4244701213
	redirect (6), v: 1, checksum: 0x7034 (incorrect should be 0x36fe), holding time: 21315s, length indicator: 17
	  isonsap_string: illegal length
	  SNPA (length: 0): <empty>
	  NET (length: 4) 00.0000.00
Q.922, invalid address
UI 22! ES-IS, length 65565
	ESH (2), v: 1, checksum: 0x70a1 (incorrect should be 0xfc4c), holding time: 21315s, length indicator: 17
	  Number of Source Addresses: 3
	  NET (length: 0): isonsap_string: illegal length
	  NET (length: 4): ec.ff00.00
	  NET (length: 0): isonsap_string: illegal length
UI 22! ES-IS, length 65565
	redirect (6), v: 1, checksum: 0x7034 (incorrect should be 0x3ff0), holding time: 21315s, length indicator: 17
	  04
	  SNPA (length: 4): 00:00:00:00, bad opts/li
UI 22! ES-IS, length 65565
	ESH (2), v: 1, checksum: 0x70a1 (incorrect should be 0xfb4e), holding time: 21315s, length indicator: 17
	  Number of Source Addresses: 2
	  NET (length: 0): isonsap_string: illegal length
	  NET (length: 4): ec.ff00.00, bad opts/li
UI 22! ES-IS, length 65565
	redirect (6), v: 1, checksum: 0xffff (incorrect should be 0x6b16), holding time: 21253s, length indicator: 17
	  00.04ec.0000
	  SNPA (length: 0): <empty>, bad opts/li
Q.922, hdr-len 2, DLCI 0, Flags [FECN], NLPID unknown (0x22), length 72482: 
	0x0000:  0082 1000 5542 5343 70a1 0200 0400 0000  ....UBSCp.......
	0x0010:  007e                                     .~