Technical details:
Access-Request packet with a malformed Tunnel-Password attribute triggers the invocation of memcpy() with a negative third argument, thereby causing radiusd to crash.
Below is the snip of vulnerable code from src/lib/radius.c: [snip]
int rad_decode(RADIUS_PACKET *packet, RADIUS_PACKET *original,
const char *secret)
{
DICT_ATTR *attr;
uint32_t lvalue;
uint32_t vendorcode;
VALUE_PAIR **tail;
VALUE_PAIR *pair;
uint8_t *ptr;
int length;
int attribute;
int attrlen;
int vendorlen;
radius_packet_t *hdr;
if ((pair = malloc(sizeof(VALUE_PAIR))) == NULL) {
pairfree(&packet->vps);
librad_log("out of memory");
errno = ENOMEM;
return -1;
}
memset(pair, 0, sizeof(VALUE_PAIR));
...
/* EL: Now we have pair->length == 0 */
pair->attribute = attribute;
pair->length = attrlen;
pair->operator = T_OP_EQ;
pair->next = NULL;
switch (pair->type) {
case PW_TYPE_OCTETS:
case PW_TYPE_ABINARY:
case PW_TYPE_STRING:
if (pair->flags.has_tag &&
pair->type == PW_TYPE_STRING) {
int offset = 0;
if(TAG_VALID(*ptr)) {
pair->flags.tag = *ptr;
pair->length--;
offset = 1;
} else if (pair->flags.encrypt ==
FLAG_ENCRYPT_TUNNEL_PASSWORD) {
/*
* from RFC2868 - 3.5. Tunnel-Password
* If the value of the Tag field is greater than
* 0x00 and less than or equal to 0x1F, it SHOULD
* be interpreted as indicating which tunnel
* (of several alternatives) this attribute pertains;
* otherwise, the Tag field SHOULD be ignored.
*/
pair->flags.tag = 0x00;
/* EL: at this point we have pair->length == -1 */
pair->length--;
offset = 1;
} else {
pair->flags.tag = 0x00;
}
memcpy(pair->strvalue, ptr + offset,
pair->length);
}
[snip]
To exploit this vulnerability attacker does not need to know NAS (Network Access Server) secret as the NAS's IP address can be easily spoofed.
Solution:
S-Quadra alerted FreeRADIUS team of this issue on 20th November 2003, a fix was available in CVS after several hours.
Unfortunately, the first attempt to contact with FreeRADIUS development team was made through post a to freeradius-users mailing list, as page http://www.freeradius.org/usage.html#help ("reporting bugs" section) states. We admit that such behavior is NOT correct and our further FreeRADIUS security reports will be issued directly to freeradius-devel mailing list.
Also, apparently, despite the post to freeradius-user list of the person claiming to be "Chris Parker", we have some knowledge of "how radius works" and PoC included in this advisory.
Proof of concept:
The following command will crash the radiusd daemon: