xorl %eax, %eax

CVE-2008-5514: University of Washington IMAP c-client Remote Memory Corruption

leave a comment »

This vulnerability was reported by Ludwig Nussel and it is located at src/c-client/rfc822.c and specifically in the routine below…

/* Output character to buffer
 * Accepts: buffer
 *	    character to write
 * Returns: T if success, NIL if error
 */

static long rfc822_output_char (RFC822BUFFER *buf,int c)
{
  *buf->cur++ = c;		/* add character, soutr buffer if full */
  return (buf->cur == buf->end) ? rfc822_output_flush (buf) : LONGT;
}

This is a helper function that is used to output the character passed to it as the second argument to the buffer which is its first argument. For completeness, here is the ‘RFC822BUFFER’ data type as it was defined in src/c-client/rfc822.h:

typedef struct rfc822buffer {
  soutr_t f;			/* I/O flush routine */
  void *s;			/* stream for I/O routine */
  char *beg;			/* start of buffer */
  char *cur;			/* current buffer pointer */
  char *end;			/* end of buffer */
} RFC822BUFFER;

Back to rfc822_output_char(), the code is quite simple. It sets the next character to the ‘c’ one using ‘buf->cur’ that points to the current location inside the buffer without performing any bound checks before doing so. Then, if the current position inside the buffer has reached then end, it will call rfc822_output_flush() to flush the buffer since it is full, otherwise it will just return ‘LONGT’. Of course, the above code doesn’t perform any bound checks and thus it can easily result in an off-by-one overwrite. If this happens and then a call to rfc822_output_data() takes place the code below will be reached.

/* Output data to buffer
 * Accepts: buffer
 *	    data to write
 *	    size of data
 * Returns: T if success, NIL if error
 */

static long rfc822_output_data (RFC822BUFFER *buf,char *string,long len)
{
  while (len) {			/* until request satified */
    long i;
    if (i = min (len,buf->end - buf->cur)) {
      memcpy (buf->cur,string,i);
      buf->cur += i;		/* blat data */
      string += i;
      len -= i;
    }
				/* soutr buffer now if full */
     if (len && !rfc822_output_flush (buf)) return NIL;
  }
  return LONGT;
}

You can determine the purpose of this routine from the provided comments, but the important part is that that inside the ‘while’ loop you can see that it uses min() to select between ‘len’ and ‘buf->end – buf->cur’ as the size limit passed to memcpy() to copy the buffer. However, since both values passed to min() are of signed types and because of the previous off-by-one overwrite the ‘buf->end – buf->cur’ can result in a negative value and specifically, -1. This will, of course, lead to memory corruption.
Finally, if ‘len’ isn’t 0 and rfc822_output_flush() returns NULL, the function will immediately exit with NIL. To fix this overflow the following patch was applied:

      len -= i;
    }
				/* soutr buffer now if full */
-    if (len && !rfc822_output_flush (buf)) return NIL;
+     if ((len || (buf->cur == buf->end)) && !rfc822_output_flush (buf))
+ 		return NIL;

  }
  return LONGT;
}

To check not only for the ‘len’ and return value of rfc822_output_flush() but also that the buffer’s pointer hasn’t reached its end. Additionally, rfc822_output_char() was updated to check the buffer’s limits before performing any copy operations like this:

   static long rfc822_output_char (RFC822BUFFER *buf,int c)
   {
+   if ((buf->cur == buf->end) && !rfc822_output_flush (buf)) return NIL;
     *buf->cur++ = c;		/* add character, soutr buffer if full */
     return (buf->cur == buf->end) ? rfc822_output_flush (buf) : LONGT;
   }

According to its CVE name description this vulnerability is exploitable through an email that will be processed by the above routines.

Written by xorl

January 2, 2010 at 16:05

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