CVE-2009-2651: Asterisk RTP NULL Pointer Dereference
This bug was reported by Marcus Hunger on 27 July 2009 and it affects 1.6 up to, and including 1.6.1.1. Here is the vulnerable code found at main/rtp.c.
struct ast_frame *ast_rtp_read(struct ast_rtp *rtp) { int res; struct sockaddr_in sock_in; socklen_t len; unsigned int seqno; ... if (rtp->f.subclass == AST_FORMAT_T140RED) { unsigned char *data = rtp->f.data.ptr; unsigned char *header_end; int num_generations; int header_length; int length; int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/ int x; rtp->f.subclass = AST_FORMAT_T140; header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen); header_end++; header_length = header_end - data; num_generations = header_length / 4; length = header_length; ... return &rtp->f; }
ast_rtp is a huge structure that contains RTP session description. If the session’s format is that of AST_FORMAT_T140, meaning “Passthrough T.140 Realtime Text” as we can read from main/frame.c. Integer ‘diff’ will be initialized to the sequence number, and ‘header_end’ pointer will be initialized with the location of ((*data) & 0x7f) in the user controlled ‘data’ buffer. However, from memchr(3) man page we can read:
RETURN VALUE The memchr() and memrchr() functions return a pointer to the matching byte or NULL if the character does not occur in the given memory area.
So, if that character is not present inside the user controlled ‘data’ buffer, pointer ‘header_end’ will be set to NULL and the subsequent use of that variable results in a NULL pointer dereference. The fix to this bug was quite simple…
header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen); + if (header_end == NULL) { + return &ast_null_frame; + } header_end++;
Just a simple check of the return value of memchr(3).
Leave a Reply