#!/p/perl5.000/perl5.000 -w # # Detect SATAN scan by analysing the TCP wrapper output. # # Usage: detect_satan -l # # Author: Mark Crosbie March 1995 # mcrosbie@cs.purdue.edu # # v1.0 - Initial design using tail on the inetdlog # Detects SATAN/SANTA scans by examining the output of the TCP wrappers # package. Accumulates evidence for a scan and then prints a warning once # a threshold of evidence is reached. # These constants are easily modified. # # The tool is far from perfect - it will only detect HEAVY scans in its # current form. This will be changed later as it is integrated with other # tools. # # Options: # -v turn on verbose mode to print things as they happen # -l gives the name of the log file containing TCP wrappers # output # -t gives the path to the tail program require 'getopts.pl'; $usage = "detect_satan [-l ] [-t ; $junk = ''; # match for certain specific occurances of things that indicate SATAN # running # default to wait for a minute $timeout = $TIMEOUT_VAL; # no evidence yet $satan_evidence = 0; print "\nWaiting for SATAN scans...\n"; # for as long as you fear SATAN... while(1) { # wait for either the log file to have something written to it, or for the # timer to expire. If the timer expires, handle the aggregate statistics # If the log file has new data, read that and update the statistics $rin = ''; vec($rin, fileno(LOG), 1) = 1; $rfd = $rin; # wait for either a timeout or a line to be written to the file ($nfound, $timeleft) = select($rfd, undef, undef, $timeout); $timeleft = $TIMEOUT_VAL; # determine if we timed out or if there is something to read. if($nfound == 0) { # there must have been a time-out, so gather some aggregate statistics if($finger_attempts >= $FINGER_THRESHOLD) { $satan_evidence++; $finger_attempts = 0; } if($comsat_attempts >= $COMSAT_THRESHOLD) { $satan_evidence++; $comsat_attempts = 0; } if($quotad_attempts >= $QUOTAD_THRESHOLD) { $satan_evidence++; $quotad_attempts = 0; } if($rexecd_attempts >= $REXECD_THRESHOLD) { $satan_evidence++; $rexecd_attempts = 0; } if($sprayd_attempts >= $SPRAYD_THRESHOLD) { $satan_evidence++; $sprayd_attempts = 0; } if($cmsd_attempts >= $CMSD_THRESHOLD) { $satan_evidence++; $cmsd_attempts = 0; } if($walld_attempts >= $WALLD_THRESHOLD) { $satan_evidence++; $walld_attempts = 0; } # determine, based on accumulated evidence, whether we have been scanned by # SATAN if($satan_evidence >= $SATAN_THRESHOLD) { # the src array has counts for each possible scanning host print "\nWARNING: Possible SATAN scan.\n"; print "Originating scanning hosts:\n"; foreach $host (keys(%src)) { print "$host : ".$src{$host}."\n"; } $satan_evidence = 0; undef %src; } $timeout = $TIMEOUT_VAL; # wait for the timeout } else { # the time left to wait should be used as a new timeout $timeout = $TIMEOUT_VAL / 2; # set stdout to be autoflushed select((select(STDOUT), $| = 1)[0]); # there is something to read - read it while you can. $_ = ; chop; @line = split; if($line[4] =~ "finger") { $finger_attempts++; $src{$line[7]}++; print "Finger from $line[7]...\n" if $opt_d; } if($line[4] =~ "comsat") { $comsat_attempts++; $src{$line[7]}++; print "comsat from $line[7]...\n" if $opt_d; } if($line[4] =~ "rexecd") { $rexecd_attempts++; $src{$line[7]}++; print "rexecd from $line[7]...\n" if $opt_d; } if($line[4] =~ "sprayd") { $src{$line[7]}++; $sprayd_attempts++; print "sprayd from $line[7]...\n" if $opt_d; } if($line[4] =~ "rquotad") { $src{$line[7]}++; $quotad_attempts++; print "rquotad from $line[7]...\n" if $opt_d; } if($line[4] =~ "cmsd") { $src{$line[7]}++; $cmsd_attempts++; print "cmsd from $line[7]...\n" if $opt_d; } if($line[4] =~ "walld") { $src{$line[7]}++; $walld_attempts++; print "walld from $line[7]...\n" if $opt_d; } } } close(LOG); exit; # interrupt handler - if Ctrl-C typed then this is called to give some # summary stats. sub report { print "\nSATAN SCAN DETECTION REPORT:\n"; # finger attempts, print how many and from where if($finger_attempts > 0) { print "\nFINGER ATTEMPTS: $finger_attempts\n"; } # rexecd attempts, print how many and from where if($rexecd_attempts > 0) { print "\nREXECD ATTEMPTS: $rexecd_attempts\n"; } # comsat attempts, print how many and from where if($comsat_attempts > 0) { print "\nCOMSAT ATTEMPTS:$comsat_attempts\n"; } # sprayd attempts, print how many and from where if($sprayd_attempts > 0) { print "\nSPRAYD ATTEMPTS: $sprayd_attempts\n"; } # cmsd attempts, print how many and from where if($cmsd_attempts > 0) { print "\nCMSD ATTEMPTS: $cmsd_attempts\n"; } # quotad attempts, print how many and from where if($quotad_attempts > 0) { print "\nQUOTAD ATTEMPTS: $quotad_attempts\n"; } # attempts, print how many and from where if($walld_attempts > 0) { print "\nWALLD ATTEMPTS: $walld_attempts\n"; } print "Suspicion level: $satan_evidence\n"; print "\n"; exit; }