		/* webscan.c - 1999 (c) Mixter */
	/* compile: gcc -O2 -Wall webscan.c -o webscan */

#define INITIAL_TIMEOUT	5	// how long to wait for a connection
#define WAIT_FORK 1500000	// wait between forks in ms
#define VERSION	  "ver.log"
#define VULN	  "vuln.log"
#define STATUSLOG "status.log"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#define SSA sizeof(struct sockaddr)
#define SOX socket(AF_INET,SOCK_STREAM,0)

void usage(char *name, char *text);	// print usage & die
int validip(char *);			// check and correct ip address
void fchk(FILE *);			// check a file
void timedout(int);			// dummy sighandler function
int background(void);			// background a process
void sk4n(char *);			// log services for one ip
int y2ksucks (char *);			// strstr replacement

char *buff[100];
char *cginame[100];
int timeout = INITIAL_TIMEOUT;

int main(int argc,char **argv)
{
 FILE *data,*err;
 char ip[30];
 int pid;

 if((argc!=2)) usage(argv[0],"<ipfile>");

 fprintf(stderr,"[0;36mweb scan 1.1 by [5mMixter[0m\n");
 fprintf(stderr,"[0;36mscanning from %s (pid: %d)[0m\n"
                 ,argv[1] ,(pid=background()));

 signal(SIGHUP,SIG_IGN);
 signal(SIGCHLD,SIG_IGN);	// zombies suck

 fchk(data=fopen(argv[1],"r"));
 fchk(err=fopen(STATUSLOG,"a"));

 fprintf(err,"Started new session. File: %s, PID: %d\n",argv[1],pid);
 fflush(err);

  buff[1] = "GET /cgi-bin/unlg1.1 HTTP/1.0\n\n";
  buff[2] = "GET /cgi-bin/rwwwshell.pl HTTP/1.0\n\n";
  buff[3] = "GET /cgi-bin/phf HTTP/1.0\n\n";
  buff[4] = "GET /cgi-bin/Count.cgi HTTP/1.0\n\n";
  buff[5] = "GET /cgi-bin/test-cgi HTTP/1.0\n\n";
  buff[6] = "GET /cgi-bin/nph-test-cgi HTTP/1.0\n\n";
  buff[7] = "GET /cgi-bin/nph-publish HTTP/1.0\n\n";
  buff[8] = "GET /cgi-bin/php.cgi HTTP/1.0\n\n";
  buff[9] = "GET /cgi-bin/handler HTTP/1.0\n\n";
  buff[10] = "GET /cgi-bin/webgais HTTP/1.0\n\n";
  buff[11] = "GET /cgi-bin/websendmail HTTP/1.0\n\n";
  buff[12] = "GET /cgi-bin/webdist.cgi HTTP/1.0\n\n";
  buff[13] = "GET /cgi-bin/faxsurvey HTTP/1.0\n\n";
  buff[14] = "GET /cgi-bin/htmlscript HTTP/1.0\n\n";
  buff[15] = "GET /cgi-bin/pfdispaly.cgi HTTP/1.0\n\n";
  buff[16] = "GET /cgi-bin/perl.exe HTTP/1.0\n\n";
  buff[17] = "GET /cgi-bin/wwwboard.pl HTTP/1.0\n\n";
  buff[18] = "GET /cgi-bin/www-sql HTTP/1.0\n\n";
  buff[19] = "GET /cgi-bin/view-source HTTP/1.0\n\n";
  buff[20] = "GET /cgi-bin/campas HTTP/1.0\n\n";
  buff[21] = "GET /cgi-bin/aglimpse HTTP/1.0\n\n";
  buff[22] = "GET /cgi-bin/glimpse HTTP/1.0\n\n";
  buff[23] = "GET /cgi-bin/man.sh HTTP/1.0\n\n";
  buff[24] = "GET /cgi-bin/AT-admin.cgi HTTP/1.0\n\n";
  buff[25] = "GET /cgi-bin/filemail.pl HTTP/1.0\n\n";
  buff[26] = "GET /cgi-bin/maillist.pl HTTP/1.0\n\n";
  buff[27] = "GET /cgi-bin/jj HTTP/1.0\n\n";
  buff[28] = "GET /cgi-bin/info2www HTTP/1.0\n\n";
  buff[29] = "GET /cgi-bin/files.pl HTTP/1.0\n\n";
  buff[30] = "GET /cgi-bin/finger HTTP/1.0\n\n";
  buff[31] = "GET /cgi-bin/bnbform.cgi HTTP/1.0\n\n";
  buff[32] = "GET /cgi-bin/survey.cgi HTTP/1.0\n\n";
  buff[33] = "GET /cgi-bin/AnyForm2 HTTP/1.0\n\n";
  buff[34] = "GET /cgi-bin/textcounter.pl HTTP/1.0\n\n";
  buff[35] = "GET /cgi-bin/classifieds.cgi HTTP/1.0\n\n";
  buff[36] = "GET /cgi-bin/environ.cgi HTTP/1.0\n\n";
  buff[37] = "GET /cgi-bin/wrap HTTP/1.0\n\n";
  buff[38] = "GET /cgi-bin/cgiwrap HTTP/1.0\n\n";
  buff[39] = "GET /cgi-bin/guestbook.cgi HTTP/1.0\n\n";
  buff[40] = "GET /cgi-bin/edit.pl HTTP/1.0\n\n";
  buff[41] = "GET /cgi-bin/perlshop.cgi HTTP/1.0\n\n";
  buff[42] = "GET /_vti_inf.html HTTP/1.0\n\n";
  buff[43] = "GET /_vti_pvt/service.pwd HTTP/1.0\n\n";
  buff[44] = "GET /_vti_pvt/users.pwd HTTP/1.0\n\n";
  buff[45] = "GET /_vti_pvt/authors.pwd HTTP/1.0\n\n";
  buff[46] = "GET /_vti_pvt/administrators.pwd HTTP/1.0\n\n";
  buff[47] = "GET /_vti_bin/shtml.dll HTTP/1.0\n\n";
  buff[48] = "GET /_vti_bin/shtml.exe HTTP/1.0\n\n";
  buff[49] = "GET /cgi-dos/args.bat HTTP/1.0\n\n";
  buff[50] = "GET /cgi-win/uploader.exe HTTP/1.0\n\n";
  buff[51] = "GET /cgi-bin/rguest.exe HTTP/1.0\n\n";
  buff[52] = "GET /cgi-bin/wguest.exe HTTP/1.0\n\n";
  buff[53] = "GET /scripts/issadmin/bdir.htr HTTP/1.0\n\n";
  buff[54] = "GET /scripts/CGImail.exe HTTP/1.0\n\n";
  buff[55] = "GET /scripts/tools/newdsn.exe HTTP/1.0\n\n";
  buff[56] = "GET /scripts/fpcount.exe HTTP/1.0\n\n";
  buff[57] = "GET /cfdocs/expelval/openfile.cfm HTTP/1.0\n\n";
  buff[58] = "GET /cfdocs/expelval/exprcalc.cfm HTTP/1.0\n\n";
  buff[59] = "GET /cfdocs/expelval/displayopenedfile.cfm HTTP/1.0\n\n";
  buff[60] = "GET /cfdocs/expelval/sendmail.cfm HTTP/1.0\n\n";
  buff[61] = "GET /iissamples/exair/howitworks/codebrws.asp HTTP/1.0\n\n";
  buff[62] = "GET /iissamples/sdk/asp/docs/codebrws.asp HTTP/1.0\n\n";
  buff[63] = "GET /msads/Samples/SELECTOR/showcode.asp HTTP/1.0\n\n";
  buff[64] = "GET /search97.vts HTTP/1.0\n\n";
  buff[65] = "GET /carbo.dll HTTP/1.0\n\n";
  cginame[1] = "UnlG - backd00r ";
  cginame[2] = "THC - backd00r  ";
  cginame[3] = "phf..classic :) ";
  cginame[4] = "Count.cgi       ";
  cginame[5] = "test-cgi        ";
  cginame[6] = "nph-test-cgi    ";
  cginame[7] = "nph-publish     ";
  cginame[8] = "php.cgi         ";
  cginame[9] = "handler         ";
  cginame[10] = "webgais         ";
  cginame[11] = "websendmail     ";
  cginame[12] = "webdist.cgi     ";
  cginame[13] = "faxsurvey       ";
  cginame[14] = "htmlscript      ";
  cginame[15] = "pfdisplay       ";
  cginame[16] = "perl.exe        ";
  cginame[17] = "wwwboard.pl     ";
  cginame[18] = "www-sql         ";
  cginame[19] = "view-source     ";
  cginame[20] = "campas          ";
  cginame[21] = "aglimpse        ";
  cginame[22] = "glimpse         ";
  cginame[23] = "man.sh          ";
  cginame[24] = "AT-admin.cgi    ";
  cginame[25] = "filemail.pl     ";
  cginame[26] = "maillist.pl     ";
  cginame[27] = "jj              ";
  cginame[28] = "info2www        ";
  cginame[29] = "files.pl        ";
  cginame[30] = "finger          ";
  cginame[31] = "bnbform.cgi     ";
  cginame[32] = "survey.cgi      ";
  cginame[33] = "AnyForm2        ";
  cginame[34] = "textcounter.pl  ";
  cginame[35] = "classifields.cgi";
  cginame[36] = "environ.cgi     ";
  cginame[37] = "wrap            ";
  cginame[38] = "cgiwrap         ";
  cginame[39] = "guestbook.cgi   ";
  cginame[40] = "edit.pl         ";
  cginame[41] = "perlshop.cgi    ";
  cginame[42] = "_vti_inf.html   ";
  cginame[43] = "service.pwd     ";
  cginame[44] = "users.pwd       ";
  cginame[45] = "authors.pwd     ";
  cginame[46] = "administrators  ";
  cginame[47] = "shtml.dll       ";
  cginame[48] = "shtml.exe       ";
  cginame[49] = "args.bat        ";
  cginame[50] = "uploader.exe    ";
  cginame[51] = "rguest.exe      ";
  cginame[52] = "wguest.exe      ";
  cginame[53] = "bdir - samples  ";
  cginame[54] = "CGImail.exe     ";
  cginame[55] = "newdsn.exe      ";
  cginame[56] = "fpcount.exe     ";
  cginame[57] = "openfile.cfm    ";
  cginame[58] = "exprcalc.cfm    ";
  cginame[59] = "dispopenedfile  ";
  cginame[60] = "sendmail.cfm    ";
  cginame[61] = "codebrws.asp    ";
  cginame[62] = "codebrws.asp 2  ";
  cginame[63] = "showcode.asp    ";
  cginame[64] = "search97.vts    ";
  cginame[65] = "carbo.dll       ";

 while(!feof(data))
 {
  fscanf(data,"%s\n",ip);
  if(validip(ip)==1)
  {
  usleep(WAIT_FORK);	// wait between fork()'s (1/2 second default)
  if ((pid=vfork()) < 0) { perror("fork"); exit(1); }
  if (pid==0)		// child
     {
     sk4n(ip);		// collect data for this host & save into files
     raise(9);
     return 0;
     }
  }
  else fprintf(err,"Invalid IP: %s\n",ip);
 }
 while(1) {}
 sleep(120);		// wait for the last childs
 fprintf(err,"Finished session. File: %s\n",argv[1]);

 return 0;
}

/* parts from this function are from
 * cgiscan1.35 (c) [CKS & Fdisk]
 * and httpver (c) Shok */

void sk4n (char *host)
{
  struct sockaddr_in sin;
  int sock,i,numbytes,count=0;
  char cgibuff[1024];
  char buffer[170];
  char *p;
  FILE *f1,*f2;

  sin.sin_family=AF_INET;
  sin.sin_port=htons(80);
  sin.sin_addr.s_addr=inet_addr(host);
  sock=socket(AF_INET, SOCK_STREAM, 0);
  alarm(0); signal(SIGALRM,timedout); alarm(timeout);
  connect(sock, (struct sockaddr*)&sin, sizeof(sin));
  alarm(0);
  send(sock, "GET / HTTP/1.0\n\n",16,0);
  fchk(f1=fopen(VERSION,"a"));
  fchk(f2=fopen(VULN,"a"));
  for (i=0;i<5;i++) {
        bzero(buffer,sizeof(buffer));
        if((numbytes=recv(sock, buffer, 169, 0)) < 1) break;
        p=strstr(buffer, "Server");
        if(p==NULL) continue;
        else *p+=7;
        fprintf(f1,"%s - %s\n", host , p);
  }
  close(sock);
  while(count++ <= 65)
  {
    sock=socket(AF_INET, SOCK_STREAM, 0);
    alarm(0); signal(SIGALRM,timedout); alarm(timeout);
    connect(sock, (struct sockaddr*)&sin, sizeof(sin));
    alarm(0);
    bzero(cgibuff,sizeof(cgibuff));
    send(sock, buff[count],strlen(buff[count]),0);
    recv(sock, cgibuff, sizeof(cgibuff),0);
    if(y2ksucks(cgibuff))
      fprintf(f2,"%s - %s\n",host,cginame[count]);
    close(sock);
  }
}

void usage(char *name,char *text)
{
printf("usage: %s %s\n",name,text);
exit(EXIT_FAILURE);
}

int validip(char *ip)
{
int a,b,c,d,*x;
sscanf(ip,"%d.%d.%d.%d",&a,&b,&c,&d);
x=&a;
if(*x < 0) return 0; if(*x > 255) return 0;
x=&b;
if(*x < 0) return 0; if(*x > 255) return 0;
x=&c;
if(*x < 0) return 0; if(*x > 255) return 0;
x=&d;
if(*x < 0) return 0; if(*x > 255) return 0;
sprintf(ip,"%d.%d.%d.%d",a,b,c,d); // truncate possible garbage data
return 1;
}

void fchk(FILE *fp)
{
if(fp==NULL)
{
fprintf(stderr,"Error opening file or socket.\n");
exit(EXIT_FAILURE);
}
return;
}

void timedout(int sig)
{
 alarm(0);
 raise(9);
}

int background()
{
int pid;
signal(SIGCHLD,SIG_IGN);
pid = fork();
if(pid>0) 
{
sleep(1);
exit(EXIT_SUCCESS);	// parent, exit
}
if(pid==0)
{
signal(SIGCHLD,SIG_DFL);
return getpid();		// child, go on
}
return -1;			// fork failed
}

int
y2ksucks (char *buf)
{
  int i;

  for (i = 2; i <= (int) strlen (buf); i++)
    if ((buf[i] == '0') && (buf[i - 1] == '0') &&
        (buf[i - 2] == '2') && (buf[i + 1] != '0'))
      return 1;

  return 0;
}

