CVE-2017-5337 (published 2017-03-24T15:59Z)

Multiple heap-based buffer overflows in the read_attribute function in GnuTLS before 3.3.26 and 3.5.x before 3.5.8 allow remote attackers to have unspecified impact via a crafted OpenPGP certificate.

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-119
cwe_name: Improper Restriction of Operations within the Bounds of a Memory Buffer
description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
extended_description: 
            Certain languages allow direct addressing of memory locations and do not automatically ensure that these locations are valid for the memory buffer that is being referenced. This can cause read or write operations to be performed on memory locations that may be associated with other variables, data structures, or internal program data.
         
         

Fix information:
repo_url: https://gitlab.com/gnutls/gnutls
commit_details: repo_url: https://gitlab.com/gnutls/gnutls
author: Nikos Mavrogiannopoulos
author_date: 2017-01-04 14:42:03+01:00
msg: opencdk: read_attribute: added more precise checks when reading stream

That addresses heap read overflows found using oss-fuzz:
  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=338
  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=346

Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
repository: repo_url: https://gitlab.com/gnutls/gnutls
repo_name: visit repo url
description: visit repo url
repo_language: visit repo url
owner: gnutls
file_changes: filename: read-packet.c
change_type: ModificationType.MODIFY
diff: @@ -482,46 +482,64 @@ read_attribute(cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t attr,
 		return CDK_Out_Of_Core;
 	rc = stream_read(inp, buf, pktlen, &nread);
 	if (rc) {
-		cdk_free(buf);
-		return CDK_Inv_Packet;
+		gnutls_assert();
+		rc = CDK_Inv_Packet;
+		goto error;
 	}
+
 	p = buf;
 	len = *p++;
 	pktlen--;
+
 	if (len == 255) {
+		if (pktlen < 4) {
+			gnutls_assert();
+			rc = CDK_Inv_Packet;
+			goto error;
+		}
+
 		len = _cdk_buftou32(p);
 		p += 4;
 		pktlen -= 4;
 	} else if (len >= 192) {
 		if (pktlen < 2) {
-			cdk_free(buf);
-			return CDK_Inv_Packet;
+			gnutls_assert();
+			rc = CDK_Inv_Packet;
+			goto error;
 		}
+
 		len = ((len - 192) << 8) + *p + 192;
 		p++;
 		pktlen--;
 	}
 
-	if (*p != 1) {		/* Currently only 1, meaning an image, is defined. */
-		cdk_free(buf);
-		return CDK_Inv_Packet;
+	if (!len || *p != 1) {		/* Currently only 1, meaning an image, is defined. */
+		rc = CDK_Inv_Packet;
+		goto error;
 	}
+
 	p++;
 	len--;
 
 	if (len >= pktlen) {
-		cdk_free(buf);
-		return CDK_Inv_Packet;
+		rc = CDK_Inv_Packet;
+		goto error;
 	}
+
 	attr->attrib_img = cdk_calloc(1, len);
 	if (!attr->attrib_img) {
-		cdk_free(buf);
-		return CDK_Out_Of_Core;
+		rc = CDK_Out_Of_Core;
+		goto error;
 	}
+
 	attr->attrib_len = len;
 	memcpy(attr->attrib_img, p, len);
 	cdk_free(buf);
 	return rc;
+
+ error:
+	cdk_free(buf);
+	return rc;
 }
 
 

programming_language: C