CVE-2017-13015 (published 2017-09-14T06:29Z)

The EAP parser in tcpdump before 4.9.2 has a buffer over-read in print-eap.c:eap_print().

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-125
cwe_name: Out-of-bounds Read
description: The product reads data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         

Fix information:
repo_url: https://github.com/the-tcpdump-group/tcpdump
commit_details: repo_url: https://github.com/the-tcpdump-group/tcpdump
author: Guy Harris
author_date: 2017-03-16 12:02:20-07:00
msg: CVE-2017-13015/EAP: Add more bounds checks.

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.
repository: repo_url: https://github.com/the-tcpdump-group/tcpdump
repo_name: the-tcpdump-group/tcpdump
description: the TCPdump network dissector
repo_language: C
owner: the-tcpdump-group
file_changes: filename: print-eap.c
change_type: ModificationType.MODIFY
diff: @@ -182,7 +182,9 @@ eap_print(netdissect_options *ndo,
 
     switch (eap->type) {
     case EAP_FRAME_TYPE_PACKET:
+        ND_TCHECK_8BITS(tptr);
         type = *(tptr);
+        ND_TCHECK_16BITS(tptr+2);
         len = EXTRACT_16BITS(tptr+2);
         ND_PRINT((ndo, ", %s (%u), id %u, len %u",
                tok2str(eap_code_values, "unknown", type),
@@ -193,10 +195,11 @@ eap_print(netdissect_options *ndo,
         ND_TCHECK2(*tptr, len);
 
         if (type <= 2) { /* For EAP_REQUEST and EAP_RESPONSE only */
+            ND_TCHECK_8BITS(tptr+4);
             subtype = *(tptr+4);
             ND_PRINT((ndo, "\n\t\t Type %s (%u)",
-                   tok2str(eap_type_values, "unknown", *(tptr+4)),
-                   *(tptr + 4)));
+                   tok2str(eap_type_values, "unknown", subtype),
+                   subtype));
 
             switch (subtype) {
             case EAP_TYPE_IDENTITY:
@@ -222,6 +225,7 @@ eap_print(netdissect_options *ndo,
                  * type one octet per type
                  */
                 while (count < len) {
+                    ND_TCHECK_8BITS(tptr+count);
                     ND_PRINT((ndo, " %s (%u),",
                            tok2str(eap_type_values, "unknown", *(tptr+count)),
                            *(tptr + count)));
@@ -230,19 +234,23 @@ eap_print(netdissect_options *ndo,
                 break;
 
             case EAP_TYPE_TTLS:
-                ND_PRINT((ndo, " TTLSv%u",
-                       EAP_TTLS_VERSION(*(tptr + 5)))); /* fall through */
             case EAP_TYPE_TLS:
+                ND_TCHECK_8BITS(tptr + 5);
+                if (subtype == EAP_TYPE_TTLS)
+                    ND_PRINT((ndo, " TTLSv%u",
+                           EAP_TTLS_VERSION(*(tptr + 5))));
                 ND_PRINT((ndo, " flags [%s] 0x%02x,",
                        bittok2str(eap_tls_flags_values, "none", *(tptr+5)),
                        *(tptr + 5)));
 
                 if (EAP_TLS_EXTRACT_BIT_L(*(tptr+5))) {
+                    ND_TCHECK_32BITS(tptr + 6);
 		    ND_PRINT((ndo, " len %u", EXTRACT_32BITS(tptr + 6)));
                 }
                 break;
 
             case EAP_TYPE_FAST:
+                ND_TCHECK_8BITS(tptr + 5);
                 ND_PRINT((ndo, " FASTv%u",
                        EAP_TTLS_VERSION(*(tptr + 5))));
                 ND_PRINT((ndo, " flags [%s] 0x%02x,",
@@ -250,6 +258,7 @@ eap_print(netdissect_options *ndo,
                        *(tptr + 5)));
 
                 if (EAP_TLS_EXTRACT_BIT_L(*(tptr+5))) {
+                    ND_TCHECK_32BITS(tptr + 6);
                     ND_PRINT((ndo, " len %u", EXTRACT_32BITS(tptr + 6)));
                 }
 
@@ -258,6 +267,7 @@ eap_print(netdissect_options *ndo,
 
             case EAP_TYPE_AKA:
             case EAP_TYPE_SIM:
+                ND_TCHECK_8BITS(tptr + 5);
                 ND_PRINT((ndo, " subtype [%s] 0x%02x,",
                        tok2str(eap_aka_subtype_values, "unknown", *(tptr+5)),
                        *(tptr + 5)));

programming_language: C
filename: TESTLIST
change_type: ModificationType.MODIFY
diff: @@ -512,6 +512,7 @@ wb-oobr			wb-oobr.pcap			wb-oobr.out	-v
 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
 
 # RTP tests
 # fuzzed pcap

programming_language: Shell
filename: eap_extract_read2_asan.out
change_type: ModificationType.ADD
diff: @@ -0,0 +1,2 @@
+EAP packet (0) v155, len 0
+	[|EAP]

programming_language: SQL