xorl %eax, %eax

CVE-2009-2651: Asterisk RTP NULL Pointer Dereference

leave a comment »

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).

Written by xorl

August 6, 2009 at 15:10

Posted in bugs

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s