[UNIX] Gaim Instant Messaging Client Remote Overflows

From: SecuriTeam (support_at_securiteam.com)
Date: 01/28/04

  • Next message: SecuriTeam: "[EXPL] Serv-U Ftp Site Chmod Long Filename Exploit"
    To: list@securiteam.com
    Date: 28 Jan 2004 10:49:40 +0200
    
    

    The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
    - - promotion

    The SecuriTeam alerts list - Free, Accurate, Independent.

    Get your security news from a reliable source.
    http://www.securiteam.com/mailinglist.html

    - - - - - - - - -

      Gaim Instant Messaging Client Remote Overflows
    ------------------------------------------------------------------------

    SUMMARY

    " <http://gaim.sourceforge.net/> Gaim is a multi-protocol instant
    messaging client for Linux, BSD, MacOS X, and Windows. It is compatible
    with AIM (Oscar and TOC protocols), ICQ, MSN Messenger, Yahoo, IRC,
    Jabber, Gadu-Gadu, and Zephyr networks."

    Several vulnerabilities were found in the instant messenger Gaim that
    allow remote compromise.

    DETAILS

    Vulnerable Systems:
     * Gaim version 0.75 or prior

    While developing a custom add-on, an integer overflow in the handling of
    AIM DirectIM packets was revealed that could lead to a remote compromise
    of the IM client. After disclosing this bug to the vendor they had to make
    a hurried release because of a change in the Yahoo connection procedure
    that rendered GAIM useless. Unfourtunately at the same time a closer look
    onto the source code revealed 11 more vulnerabilities.

    The identified problems range from simple standard stack overflows, heap
    overflows to an integer overflow that can be abused to cause a heap
    overflow. Due to the nature of instant messaging many of these bugs
    require man-in-the-middle attacks between the client and server. But the
    underlying protocols are easy to implement and MIM attacks on ordinary TCP
    sessions is a fairly simple task.

    Yahoo Octal-Encoding Decoder Out-Of-Bounds Overflow
    When the Yahoo Messenger handler decodes an octal value for Email
    notification functions, two different kinds of overflows can be triggered.
    In the gaim/src/protocols/yahoo/yahoo.c file, in function yahoo_decode():

    static char *yahoo_decode(const char *text)
       {
        char *converted;
        char *p, *n, *new;
       
        n = new = g_malloc(strlen (text) + 1);
       
        for (p = (char *)text; *p; p++, n++) {
          if (*p == '\\') {
           sscanf(p + 1, "%3o\n", (int *)n); < -------- [01]
            p += 3; < --------------------------------- [02]
          }
          else
            *n = *p;
         }
       
         *n = '\0';
         ...

    The way sscanf is used will always cause it to write 4 bytes to the
    allocated buffer. The author did not see the possibility of a malformed
    input like "\1" (the backslash is only a backslash). It is possible to
    write 1 or 2 NULL bytes past the buffer boundaries. On Linux this is
    exploitable like any heap off by one into the malloc() chunks.

    The second vulnerability is that no matter how many bytes sscanf()
    consumes it always increases the pointer by 4 bytes. This can result in
    overjumping the terminating NULL byte and with a specially prepared
    payload after the string it is possible to overwrite the heap with an
    arbitrary amount of bytes. Additionally the misuse of sscanf() caused an
    incompatibility to all big endian platforms.

    Yahoo Web Cookie Parser Overflow
    A buffer overflow is possible when parsing the cookies within the HTTP
    reply header of a yahoo web connection.
    In the gaim/src/protocols/yahoo/yahoo.c file, in function
    yahoo_web_pending():

    void yahoo_web_pending(gpointer data, gint source, ...
       {
         GaimConnection *gc = data;
         GaimAccount *account = gaim_connection_get_account(gc);
         struct yahoo_data *yd = gc->proto_data;
         char buf[1024], buf2[256], *i = buf, *r = buf2;
         int len, o = 0;
      
         len = read(source, buf, sizeof(buf));
         ...
         while ((i = strstr(i, "Set-Cookie: ")) && o < 2) {
          i += strlen("Set-Cookie: ");
          for (;*i != ';'; r++, i++) {
            *r = *i;
          }
          *r=';';
          r++;
          ...
         }
         ...

    All cookie data contained in the first 1024 bytes of an HTTP reply header
    are copied into a 256 byte buffer without a size check. Because the source
    and destination buffers are both on the stack and the stack layout will
    most probably result in the smaller buffer overflowing into the larger one
    this bug is believed not to be exploitable with a normal stack layout.

    Yahoo Login Page Name/Value Parser Overflow
    When parsing the Yahoo Login Webpage the YMSG protocol overflows stack
    buffers if the webpage returns oversized values.
    In the gaim/src/protocols/yahoo/yahoo.c, in funtion
    yahoo_login_page_hash():

    static GHashTable *yahoo_login_page_hash(const char *buf,size_t len)
       {
         GHashTable *hash = g_hash_table_new_full(g_str_hash, g_s...
         const char *c = buf;
         char *d;
         char name[64], value[64];
         while ((c < (buf + len)) && (c = strstr(c, "< input "))) {
          c = strstr(c, "name=\"") + strlen("name=\"");
          for (d = name; *c!='"'; c++, d++) < ----------- [04]
            *d = *c; < ---------/
          *d = '\0';
          d = strstr(c, "value=\"") + strlen("value=\"");
          if (strchr(c, '>') < d)
            break;
          for (c = d, d = value; *c!='"'; c++, d++) < --- [05]
            *d = *c; < -----------------------------/
          *d = '\0';
          g_hash_table_insert(hash, g_strdup(name), g_strdup(value));
         }
         return hash;
       }

    The content of the yahoo login webpage is trusted although it could be
    altered by a simple man-in-the-middle attack on the HTTP session. Name and
    value are taken directly from the page without any kind of size check.
    This results in two independent ways to overflow the stack.

    Yahoo Packet Parser Overflow
    A Yahoo Messenger packet consist of a header and a list of keys with their
    associated values. When reading an oversized keyname a standard stack
    overflow can be triggered. This is probably the most dangerous
    vulnerability because the nature of the bug makes it very easy to exploit
    and additionally a TCP man-in-the-middle attack is NOT needed. It is
    possible to send a malicious YMSG packet to the yahoo server so that it
    will be forwarded like any normal message.
    In the gaim/src/protocols/yahoo/yahoo.c file, in function
    yahoo_packet_read():

    static void yahoo_packet_read(struct yahoo_packet *pkt,
                           guchar *data, int len)
       {
         int pos = 0;
      
         while (pos + 1 < len) {
          char key[64], *value = NULL, *esc;
          int accept;
          int x;
      
          struct yahoo_pair *pair = g_new0(struct yahoo_pair, 1);
      
          x = 0;
          while (pos + 1 < len) {
            if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
            break;
            key[x++] = data[pos++]; < ----------------- [06]
          }
          key[x] = 0;
          pos += 2;
          ...

    Everytime the YMSG handler receives a complete packet it will pass it to
    this function in order to split it into its keys and values. Because the
    keyname is copied without any kind of size check into the key variable
    which is a 64 byte stackbuffer it is very easy to exploit. NOTE: This bug
    is also exploitable on systems with non executable stacks, or stack
    overflow detections as long free() exploits are possible on that platform.

    AIM/Oscar DirectIM Integer Overflow
    Integer overflow when allocating memory for a directIM packet result in a
    heap overflow. DirectIM is a client-to-client protocol and therefore does
    not require a MIM attack.
    In the gaim/src/protocols/oscar/ft.c file, in function handlehdr_odc():

    static int handlehdr_odc(aim_session_t *sess, aim_...
       {
         aim_frame_t fr;
         int ret = 0;
         aim_rxcallback_t userfunc;
         fu32_t payloadlength;
         fu16_t flags, encoding;
         char *snptr = NULL;
      
         fr.conn = conn;
      
         /* AAA - ugly */
         aim_bstream_setpos(bs, 20);
         payloadlength = aimbs_get32(bs);
      
         ...
      
         if (payloadlength) {
          char *msg;
          ...

          if (!(msg = calloc(1, payloadlength+1))) { < --- [07]
            free(snptr);
            return -ENOMEM;
          }

          while (payloadlength - recvd) {
            if (payloadlength - recvd >= 1024)
             i = aim_recv(conn->fd, &msg[recvd], 1024);
            else
       ...

    In this code snippet 'payloadlength' is taken directly from the network
    and passed to the calloc() function in an unsafe manner. A user supplied
    'payloadlength' of UINT_MAX (0xffffffff) will cause an integer overflow
    within the second parameter of calloc() and therefore only allocate a 0
    byte buffer. This problem is not an integer overflow due to a
    multiplication in calloc() and would not be fixed by the latest patches to
    calloc().

    Note that calloc(1, 0) will not return a NULL pointer but a pointer into
    the legal heap on at least all tested platforms (i.e: Linux, BSD). On BSD
    systems this is configureable but it defaults to this behaviour. After
    allocating the 0 byte buffer aim_recv() is called repeatedly by the while
    loop to read and overwrite with up to 4GB of data.

    Quoted Printable Decoder Overflow / Out-Of-Bounds Overflow
    When the MIME decoder decodes a quoted printable encoded string for Email
    notification, two different kinds of overflows are possible.
    In the gaim/src/util.c file, in function quotedp_decode():

    gaim_quotedp_decode(const char *str, char **ret_str, int ...
       {
         char *p, *n, *new;
      
         n = new = g_malloc(strlen (str) + 1);
      
         for (p = (char *)str; *p; p++, n++) {
          if (*p == '=') {
            sscanf(p + 1, "%2x\n", (int *)n); < -------- [08]
            p += 2; < --------------------------------- [09]
          }
          else if (*p == '_')
              *n = ' ';
             else
              *n = *p;
        }
      
        *n = '\0';
        ...

    This bug is very similar to the first one presented in this article
    therefore only the vulnerable piece of code is shown. See the above
    mentioned description.

    URL Parser Function Overflow
    At various places in the code, this utility function is used to split a
    URL into its parts. Because temporary fixed size stack buffers are used in
    an unsafe way, standard stack overflows can be caused.
    In the gaim/src/util.c file, in function gaim_url_parse():

    gboolean gaim_url_parse(const char *url, char **ret_host,
               int *ret_port, char **ret_path)
       {
         char scan_info[255];
         char port_str[5];
         int f;
         const char *turl;
         char host[256], path[256];
         int port = 0;
         /* hyphen at end includes it in control set */
         static char addr_ctrl[] = "A-Za-z0-9.-";
         static char port_ctrl[] = "0-9";
         static char page_ctrl[] = "A-Za-z0-9.~_/:*!@&%% =+^-";
      
         ...
         g_snprintf(scan_info, sizeof(scan_info),
                "%%[%s]:%%[%s]/%%[%s]", addr_ctrl,
                port_ctrl, page_ct

         f = sscanf(url, scan_info, host, port_str, path); < -- [10]
         ...

    Here sscanf() is again used in an unsafe manner. When this function is
    called with an oversized URL which can be triggered from several protocol
    handlers in different ways, sscanf() will overwrite the stack buffers
    'host' and 'path'. The problem at this point is that it is only possible
    to overwrite the buffers with a limited characterset which makes
    exploitation tricky.

    Extract Info Field Function Overflow
    At various places this utility function is called to copy the data between
    two tokens into a fixed size stackbuffer without a size check.
    In the gaim/src/util.c file, in function gaim_markup_extract_info_field():

    ..
       const char *p, *q;
       char buf[1024];
      
       ...
       p = strstr(str, start_token);
       ...
       p += strlen(start_token) + skip;
       ...
       q = strstr(p, end_token);
       
       if (q != NULL && (!no_value_token ||
            (no_value_token && strncmp(p, no_value

       {
         ...
         if (is_link)
         {
          strcat(dest_buffer, "< br>< a href=\"");
          memcpy(buf, p, q - p); < ---------------------- [11]
          buf[q - p] = '\0';
          ...

    Here it is obvious that if q - p is bigger than 1024 bytes, memcpy() will
    overwrite the stack which will result in a standard stack overflow. At the
    moment this routine is called from within the get_user_info functions of
    the MSN and YMSG protocol handlers.

    HTTP Proxy Connect Overflow
    When Gaim is setup to use an HTTP proxy for connecting to the server, a
    malicious HTTP proxy can exploit it.
    In the gaim/src/proxy.c file, in function http_canread():

    static void http_canread(gpointer data, gint source, GaimInputCondit...
       {
         int nlc = 0;
         int pos = 0;
         int minor, major, status, error=0;
         struct PHB *phb = data;
         char inputline[8192], *p;
      
         gaim_input_remove(phb->inpa);
      
         while ((nlc != 2) &&
            (read(source, &inputline[pos++], 1) == 1)) {
          if (inputline[pos - 1] == '\n')
            nlc++;
          else if (inputline[pos - 1] != '\r')
              nlc = 0;
        }
        inputline[pos] = '\0';
        ...

    Here the author never thought about the possibility that a proxy server
    could be malicious. The input is read into the 8192 byte 'inputline'
    buffer, byte after byte until a double \r\n is found. Because there is no
    size check at all the buffer will overflow as soon as the proxy sends more
    than 8192 bytes in a line.

    This bug is exploitable even if stack overwrite protections are in place
    because it is possible to overwrite the pointer 'phb' which points to a
    struct that contains a callback function which is later called in the
    function. By overwriting the pointer and by that controlling the callback
    function pointer it is possible to gain control over the instruction
    pointer before the function is left.

    CVE Information:
     <http://www.cve.mitre.org/cgi-bin/cvename.cgi name=CAN-2004-0005>
    CAN-2004-0005
     <http://www.cve.mitre.org/cgi-bin/cvename.cgi name=CAN-2004-0006>
    CAN-2004-0006
     <http://www.cve.mitre.org/cgi-bin/cvename.cgi name=CAN-2004-0007>
    CAN-2004-0007
     <http://www.cve.mitre.org/cgi-bin/cvename.cgi name=CAN-2004-0008>
    CAN-2004-0008

    Disclosure Timeline
     * 04. January 2004 - The Oscar filetransfer bug was sent to the Gaim
    vendor by Email. Within an hour the bug was fixed within the CVS tree
     * 10. January 2004 - The Gaim vendor released version 0.75 because of a
    Yahoo protocol change problem. A deeper analysis of the new version
    revealed more bugs: 1 fixed in 0.75, some new in 0.75 and some old which
    are still in 0.75. All these bugs were again mailed to the vendor
     * 15. January 2004 - The vendor was contacted with a patch because they
    had not fixed the bugs yet. Our Patch was applied same night
     * 16. January 2004 - Vendor-sec was contacted to coordinate the
    disclosure process. The vendor was asked by Email when 0.76 is ready to
    come out and that it should be as soon as possible because the bugfixes
    were visible in their CVS with explicit commit messages. There is no
    response to this mail until today
     * 23. January 2004 - The vendor was notified about public disclosure at
    the 26th
     * 25. January 2004 - Notification by the vendor that Gaim 0.76 release
    date is not planned yet
     * 26. January 2004 - Public Disclosure

    Patch Availability:
    Because there is no official new version out yet, you can download a diff
    against version 0.75 from
    <http://security.e-matters.de/patches/gaim-0.75-fix.diff> here. This patch
    was done by the FreeBSD security team. It is different from the official
    patches in the Gaim CVS. It is advisable to upgrade as soon as possible.

    ADDITIONAL INFORMATION

    The information has been provided by <mailto:s.esser@e-matters.de> Stefan
    Esser.
    The original article can be found at:
    <http://security.e-matters.de/advisories/012004.html>
    http://security.e-matters.de/advisories/012004.html

    ========================================

    This bulletin is sent to members of the SecuriTeam mailing list.
    To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
    In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

    ====================
    ====================

    DISCLAIMER:
    The information in this bulletin is provided "AS IS" without warranty of any kind.
    In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.


  • Next message: SecuriTeam: "[EXPL] Serv-U Ftp Site Chmod Long Filename Exploit"

    Relevant Pages