PHP PECL Radius 1.2.7 security flaw in radius_get_vendor_attr()

2013.06.30
Risk: Medium
Local: Yes
Remote: No
CWE: N/A


CVSS Base Score: 7.5/10
Impact Subscore: 6.4/10
Exploitability Subscore: 10/10
Exploit range: Remote
Attack complexity: Low
Authentication: No required
Confidentiality impact: Partial
Integrity impact: Partial
Availability impact: Partial

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. /* {{{ 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; } } @@ -898,15 +898,24 @@ struct rad_handle * } 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); } radlib_vs.h @@ -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);

References:

http://seclists.org/oss-sec/2013/q2/633


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top