/* w00w00! */

/* test-cgi trojan                                                      */
/* -------------------------------------------------------------------- */
/* Just a little utility to log information about who is exploiting us. */
/* Will mail it to root of local host, with the IP address, the web     */
/* browser, the query string, etc. It will then return a File Not Found */
/* error.								*/
/*									*/
/* Shok (Matt Conover), shok@dataforce.net                              */

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/types.h>

/* List of defines */
#define ERROR -1

#define IP "206.71.69.243" /* Set this to your IP address. */

#define ADMIN "root" /* Set this to the user (or address) of the person    */
                     /* to get phf attempts.                               */

#define FINGERPROG "/usr/bin/finger" /* Set to path of 'finger'.           */
#define MAILPROG   "/bin/mail"       /* This does have to be the 'mail'    */
                                     /* program but this is to specify the */
                                     /* path.                              */

/* This returns a '404 File Not Found' to the client. */
#define PRNSERVERR() printf("Content-type: text/html\n\n");                \
          printf("<HTML><HEAD>\n");                                        \
          printf("<TITLE>404 File Not Found</TITLE>\n");                   \
          printf("</HEAD><BODY>\n");                                       \
                                                                           \
          printf("<H1>File Not Found</H1>\n");                             \
          printf("The requested URL was not found on this server.<P>\n");  \
                                                                           \
          printf("</BODY></HTML>\n");                                      \
                                                                           \
          fflush(stdin), fflush(stdout), fflush(stderr);                  

/* Free up our structures before exiting. */
#define FREEALL() free(buf), free(cmdarg), free(address);
/* ------------------ */

void main()
{ 
  FILE *tmpfile, *fingerinfo;

  int pid;
  int fd[2];
  register int errors = 0;

  char *buf     = malloc(4096);
  char *cmdarg  = malloc(512);
  char *address = malloc(256);

  char *host         = getenv("REMOTE_HOST");
  char *addr         = getenv("REMOTE_ADDR");
  char *browser      = getenv("HTTP_USER_AGENT");
  char *query_string = getenv("QUERY_STRING"); 


  /* We check each malloc seperately so we can free */ 
  /* any previously malloc()'d buffers.             */
  if (buf == NULL) {
     perror("malloc");
     PRNSERVERR();
     exit(ERROR);
  } else memset(buf, 0, sizeof(buf));

  if (cmdarg == NULL) {
     perror("malloc");
     PRNSERVERR();
     free(buf);
     exit(ERROR);
  } else memset(cmdarg, 0, sizeof(cmdarg));

  if (address == NULL) {
     perror("malloc");
     PRNSERVERR();
     free(buf), free(cmdarg);
     exit(ERROR);
  } else memset(address, 0, sizeof(address));
  /* ----------------------------- */


  if (pipe(fd) == ERROR) {
     perror("pipe");
     PRNSERVERR();
     FREEALL();
     exit(ERROR);
  }

  bzero(buf, sizeof(buf));

  if ((pid = fork()) == ERROR) {

     openlog("test-cgi", LOG_PID, LOG_USER);
     syslog(LOG_ERR, "Unable to fork().");
     closelog();

     PRNSERVERR();
     FREEALL();
     exit(ERROR);
  }

  if (pid == 0) {
     close(fileno(stdout)), close(fileno(stderr)), close(fd[0]);
     dup2(fd[1], fileno(stdout)); /* Send all output to the pipe's output. */
     dup2(fd[1], fileno(stderr)); /* Send all errors to the pipe.          */

     sprintf(address, "@%.*s", 256 - 1, host); 

     /* Log information. */
     printf("The following person used test-cgi!\n\n");
     printf("\tHost: %s\n", host);
     printf("\tAddress: %s\n", addr);
     printf("\tBrowser type: %s\n", browser);
     printf("\tQuery String (i.e. command entered): %s\n\n", query_string); 

     printf("Information collected from fingering host (if any):\n");
     printf("---------------------------------------------------\n\n"); 
     fflush(stdout);

     if ((strcmp(address, IP) != 0) && (strcmp(address, "127.0.0.1") != 0))
        execl(FINGERPROG, "finger", address, (char *)NULL);
     else
        printf("[from the local host (%s)]\n", IP);

     printf(".\n"); /* Terminated 'mail'. */
    /* --------------- */

     FREEALL();
     exit(0);
  } else { 

     close(fileno(stdin)), close(fileno(stderr)), close(fd[1]);
     dup2(fd[0], fileno(stdin));  /* Send all input to the pipe's input. */
     dup2(fd[1], fileno(stderr)); /* Send all errors to the pipe.        */

     wait(NULL); /* Wait for child to completely finish before starting. */

     /* Setup the subject to send to mail. */
     sprintf(cmdarg, "-s \"TEST-CGI ATTEMPT FROM %.*s!\"", 
             sizeof(cmdarg) - 19, host);
 
     /* fork() another child to execute the mail program. */
     if ((pid = fork()) == ERROR) {
        perror("fork");
        PRNSERVERR();
        FREEALL();
        exit(ERROR);
    }

    if (pid == 0) execl(MAILPROG, "mail", cmdarg, ADMIN, (char *)NULL);
  }

  PRNSERVERR(); /* Just return 404 File Not Found. */
  FREEALL();
}
