CVE-2013-2220 (published 2013-07-31T13:20Z)

Buffer overflow in the radius_get_vendor_attr function in the Radius extension before 1.2.7 for PHP allows remote attackers to cause a denial of service (crash) and possibly execute arbitrary code via a large Vendor Specific Attributes (VSA) length value.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)

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://github.com/LawnGnome/php-radius
commit_details: repo_url: https://github.com/LawnGnome/php-radius
author: Adam Harvey
author_date: 2013-06-27 13:42:37-07:00
msg: Fix a security issue in radius_get_vendor_attr().

The underlying rad_get_vendor_attr() function assumed that it would always be
given valid VSA data. Indeed, the buffer length wasn't even passed in; the
assumption was that the length field within the VSA structure would be valid.

This could result in denial of service by providing a length that would be
beyond the memory limit, or potential arbitrary memory access by providing a
length greater than the actual data given.

rad_get_vendor_attr() has been changed to require the raw data length be
provided, and this is then used to check that the VSA is valid.

Conflicts:
	radlib_vs.h
repository: repo_url: https://github.com/LawnGnome/php-radius
repo_name: LawnGnome/php-radius
description: The PECL radius extension.
repo_language: C
owner: LawnGnome
file_changes: filename: radius.c
change_type: ModificationType.MODIFY
diff: @@ -541,24 +541,24 @@ PHP_FUNCTION(radius_get_attr)
 /* {{{ proto string radius_get_vendor_attr(data) */
 PHP_FUNCTION(radius_get_vendor_attr)
 {
-	int res;
-	const void *data;
+	const void *data, *raw;
 	int len;
 	u_int32_t vendor;
+	unsigned char type;
+	size_t data_len;
 
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &len) == FAILURE) {
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &raw, &len) == FAILURE) {
 		return;
 	}
 
-	res = rad_get_vendor_attr(&vendor, &data, (size_t *) &len);
-	if (res == -1) {
+	if (rad_get_vendor_attr(&vendor, &type, &data, &data_len, raw, len) == -1) {
 		RETURN_FALSE;
 	} else {
 
 		array_init(return_value);
-		add_assoc_long(return_value, "attr", res);
+		add_assoc_long(return_value, "attr", type);
 		add_assoc_long(return_value, "vendor", vendor);
-		add_assoc_stringl(return_value, "data", (char *) data, len, 1);
+		add_assoc_stringl(return_value, "data", (char *) data, data_len, 1);
 		return;
 	}
 }

programming_language: C
filename: radlib.c
change_type: ModificationType.MODIFY
diff: @@ -898,15 +898,24 @@ split(char *str, char *fields[], int maxfields, char *msg, size_t msglen)
 }
 
 int
-rad_get_vendor_attr(u_int32_t *vendor, const void **data, size_t *len)
+rad_get_vendor_attr(u_int32_t *vendor, unsigned char *type, const void **data, size_t *len, const void *raw, size_t raw_len)
 {
 	struct vendor_attribute *attr;
 
-	attr = (struct vendor_attribute *)*data;
+	if (raw_len < sizeof(struct vendor_attribute)) {
+		return -1;
+	}
+
+	attr = (struct vendor_attribute *) raw;
 	*vendor = ntohl(attr->vendor_value);
+	*type = attr->attrib_type;
 	*data = attr->attrib_data;
 	*len = attr->attrib_len - 2;
 
+	if ((attr->attrib_len + 4) > raw_len) {
+		return -1;
+	}
+
 	return (attr->attrib_type);
 }
 

programming_language: C
filename: radlib_vs.h
change_type: ModificationType.MODIFY
diff: @@ -74,7 +74,7 @@
 
 struct rad_handle;
 
-int	rad_get_vendor_attr(u_int32_t *, const void **, size_t *);
+int	rad_get_vendor_attr(u_int32_t *, unsigned char *, const void **, size_t *, const void *, size_t);
 int	rad_put_vendor_addr(struct rad_handle *, int, int, struct in_addr);
 int	rad_put_vendor_attr(struct rad_handle *, int, int, const void *,
 	    size_t);

programming_language: C