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.