Monday, January 27, 2014

VRT-2013-1001 (CVE-2013-6487): Buffer overflow in Gadu-Gadu HTTP parsing

Sourcefire Vulnerability Report VRT-2013-1001 (CVE-2013-6487): Buffer overflow in Gadu-Gadu HTTP parsing

Description

An exploitable remote code execution vulnerability exists in Pidgin's implementation of the Gadu Gadu protocol in the libpurple library. An attacker who can control the Content-Length of a HTTP request can cause an undersized allocation which can later be used to overflow into the heap. An attack requires the ability to spoof messages from the gadu-gadu.pl domain to exploit this vulnerability.

Tested Versions

Pidgin 2.10.7

Coverage

Prior coverage through an http_inspect alert GID 120, SID 8 as well as SID 2580.

Details

In gg_http_watch_fd() in file pidgin-2.10.7\libpurple\protocols\gg\lib\http.c at line 353 content-length will be read from the HTTP server:

  353     while (line) {
  354         if (!strncasecmp(line, "Content-length: ", 16)) {
  355             h->body_size = atoi(line + 16);
  356         }
  357         line = strchr(line, '\n');
  358         if (line)
  359             line++;
  360     }

It then checks if h->bodysize is less than or equal to 0, however h->body_size is an unsigned integer so a negative value will return a large positive size, meaning the check for less than zero will never be true:

  362     if (h->body_size <= 0) {
  363         gg_debug(GG_DEBUG_MISC, "=> http, content-length not found\n");
  364         h->body_size = left;
  365     }

This check will also pass because left will not be larger than a negative body_size:

  367     if (left > h->body_size) {
  368         gg_debug(GG_DEBUG_MISC, "=> http, oversized reply (%d bytes needed, %d bytes left)\n", h->body_size, left);
  369         h->body_size = left;
  370     }

if h->body_size is 4294967295 (or -1) then the below will result in a malloc(0):

  374     if (!(h->body = malloc(h->body_size + 1))) {

Finally we reach our out of bounds write into the heap here:

  381     if (left) {
  382         memcpy(h->body, tmp + sep_len, left);
  383         h->body_done = left;
  384     }

The client will keep copying data as long as there's data in the http response body and will then free the original heap chunk.
Add to Technorati Favorites Digg! This

No comments: