Talos Vulnerability Report

TALOS-2016-0143

Pidgin MXIT Suggested Contacts Memory Disclosure Vulnerability

June 21, 2016
CVE Number

CVE-2016-2375

DESCRIPTION

An exploitable out-of-bounds ready exists in the handling of the MXIT protocol in Pidgin. Specially crafted MXIT contact information sent from the server can result in memory disclosure.

CVSSv3 SCORE

5.3 CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N

TESTED VERSIONS

Pidgin 2.10.11

PRODUCT URLs

https://www.pidgin.im/

DETAILS

In the function mxitparsecmd_suggestcontacts in the file mxit/protocol.c at line 2020 the number of attributes will be read from the incoming packet into the variable count.

2020    count = atoi( records[0]->fields[3]->data );

This value is subsequently used as the bounds for a loop at line 2030 and the loop index is used as an array index at lines 2034-2036.

2030    for ( j = 0; j < count; j++ ) {

2034    fname = records[0]->fields[4 + j]->data;        /* field name */
        if ( records[i]->fcount > ( 2 + j ) )
            fvalue = records[i]->fields[2 + j]->data;   /* field value */

The pointers set at these locations will subsequently be used to read data, potentially resulting in an out-of-bounds read, copying data into results fields, for example at lines 2056-2059:

2056    else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) {
            /* nickname */
            g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
2059    }

Most of the out-of-bounds reads would simply result in a crash if a memory page is inaccessible since most information is not sent back to the server. However, when the add button is pushed, the following callback is called (defined in mxit/profile.c at lines 288-291):

static void mxit_search_results_add_cb( PurpleConnection *gc, GList *row, gpointer user_data )
{
    /* display add buddy dialog */
    purple_blist_request_add_buddy( purple_connection_get_account( gc ), g_list_nth_data( row, 0 ), NULL, g_list_nth_data( row, 1 ) );
}

The data in this row is set in mxitshowsearch_results() in mxit/profile.c at lines 340-346:

340     row = g_list_append( NULL, g_strdup_printf( "#%s", tmp ) );
341     row = g_list_append( row, g_strdup( profile->nickname ) );
        row = g_list_append( row, g_strdup( profile->firstname ) );
        row = g_list_append( row, g_strdup( profile->lastname ) );
        row = g_list_append( row, g_strdup( profile->male ? "Male" : "Female" ) );
        row = g_list_append( row, g_strdup_printf( "%i", calculateAge( profile->birthday ) ) );
346     row = g_list_append( row, g_strdup( profile->whereami ) );

This means that the nickname will be sent to the function purpleblistrequestaddbuddy() as last argument, which ends up calling:

ui_ops->request_add_buddy(account, username, group, alias);

Which should call the callback mxitaddbuddy() defined in roster.c at line 729:

void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group, const char* message )

This function then sends the alias back as a message to the server at lines 754 and 759:

741     list = purple_find_buddies( session->acc, buddy_name );
        if ( g_slist_length( list ) == 1 ) {
            purple_debug_info( MXIT_PLUGIN_ID, "mxit_add_buddy (scenario 1) (list:%i)\n", g_slist_length( list ) );
            /*
             * we only send an invite to MXit when the user is not already inside our
             * blist.  this is done because purple does an add_buddy() call when
             * you accept an invite.  so in that case the user is already
             * in our blist and ready to be chatted to.
             */

            if ( buddy_name[0] == '#' ) {
                gchar *tmp = (gchar*) purple_base64_decode( buddy_name + 1, NULL );
                if ( tmp ) {
                    754 mxit_send_invite( session, tmp, FALSE, buddy_alias, group_name, message );
                    g_free( tmp );
                }
            }
            else
759             mxit\_send\_invite( session, buddy_name, TRUE, buddy_alias, group_name, message );
760     }

TIMELINE

2016-04-13 - Vendor Notification
2016-06-21 - Public Disclosure

Credit

Discovered by Yves Younan of Cisco Talos.