Security report

Matt Jones matt at volvent.org
Thu Sep 12 20:14:27 EDT 2013


Hi,

Here is another issue that should be corrected in the libpurple
source.  More to come soon.

Regards,

Matt

msn_message_gen_payload function in libpurple/protocols/msn/Msg.c file.

char *
msn_message_gen_payload(MsnMessage *msg, size_t *ret_size)
{
GList *l;
char *n, *base, *end;
int len;
size_t body_len = 0;
const void *body;

g_return_val_if_fail(msg != NULL, NULL);

len = MSN_BUF_LEN;

base = n = end = g_malloc(len + 1);
end += len;

/* Standard header. */
if (msg->charset == NULL)
{
 g_snprintf(n, len,
      "MIME-Version: 1.0\r\n"
      "Content-Type: %s\r\n",
      msg->content_type);
}
else
{
 g_snprintf(n, len,
      "MIME-Version: 1.0\r\n"
      "Content-Type: %s; charset=%s\r\n",
      msg->content_type, msg->charset);
}

n += strlen(n);

for (l = msg->header_list; l != NULL; l = l->next)
{
 const char *key;
 const char *value;

 key = l->data;
 value = msn_message_get_header_value(msg, key);

 g_snprintf(n, end - n, "%s: %s\r\n", key, value);
 n += strlen(n);
}

n += g_strlcpy(n, "\r\n", end - n); [1]

body = msn_message_get_bin_data(msg, &body_len); [2]

if (body != NULL)
{
 memcpy(n, body, body_len); [3]
 n += body_len;
 *n = '\0'; [4]
}

if (ret_size != NULL)
{
 *ret_size = n - base;

 if (*ret_size > 1664)
  *ret_size = 1664;
}

return base;
}

Description:

The function builds an MSN message including the headers and binary
data body. It begins by setting a static header, then pushes any
optional headers one at a time.

At [1] a CRLF is appended and n is incremented, however g_strlcpy
always returns the size of the source buffer, so this will always
increment n by 2, regardless if there is room for it.

At [2] the body is fetched using msn_message_get_bin_data, which is a
simple function that just returns msg->body and sets body_len to its
length (msg->body_len).

At [3] body is concatenated onto where n is pointing to with no
validation if there's sufficient room for it, which could result in a
heap overflow.

At [4] n is NULL terminated, this could be out-of-bounds due to either
[1] pr [3].

Suggested fix:

Do not increment a pointer using the return value from g_strncpy
without validating there's sufficient room for the data.  Perform a
validation check that the body returned from msn_message_get_bin_data
can be copied to its destination.


More information about the security mailing list