#!/usr/bin/perl -w # # Snort2HTML 1.5 by Dan Swan, Oct 03, 00. # # Special thanks to Martin Roesch for writing snort, a great NIDS! # And to Max Vision for the use of his attack signatures database. # And to my girlfriend Lisa for being supportive and a hottie. # # Distribute and modify freely, but give credit where credit is due! # # # INSTALLATION: Place this file in /usr/local/bin. To update webpage # regularly, paste the following quoted text into a file named # /etc/cron.hourly/snortupdate: "/usr/local/bin/snort2html", # and make sure both files are executable. # # USAGE: ./snort2html # ./snort2html # # If no parameters are specified at the command line, the inputfile # defaults to "/var/log/secure", and the outputfile defaults to # "/home/httpd/html/snort2html.html". # # # TODO: -Display service on Target port # -More color coding of source port (suggestions welcome!) # -A cgi wrapper to update page when accessed. # -Dynamic sorting by clicking on column header. # -Command line flags to control formatting # -Neaten up script which is getting a bit messy; # # # NOTE: I am interested in any suggestions on improving the code, features # you'd like to see, or tips on making the output more lynx-freindly. # Please send them to swan_daniel@hotmail.com # # # ASSISTANCE: If you're having trouble, make sure you've read these # instructions, and are using the latest version, which is # available from: www.geocities.com/swan_daniel/snort2html.txt # If this doesn't solve your problem, re-read these # instructions, and then mail me with a description of your # problem, and a copy of your snort alert log. I'll do my best # to help you resolve your problem. # # # CHANGES: # # 1.1 # - Changed to , fixed perms on outputfile, other minor cosmetic # changes as suggested by Ralf Hildebrandt. # - Fixed problem parsing ICMP alerts, optimized code for speed (~10% gain) # using patch provided by Nico Erfuth. # # 1.2 # - Modifications made by Ralf Hildebrandt to enable parsing of spp_portscan plugin output, # thus making this snort1.6 compatible # - Fixed a silly Regep mistake that was causing dates to be outputted with a space # in between the digits. # # 1.3 # - Updated link generator to arachNIDS database to reflect new path # # 1.5 October, 2000 # - We're gonna skip a version here, as I actually did a version that # I only used myself, and never bothered to release. # - Fixed a few regexes that were breaking under some alerts. # - Added ability to specify inputfile and outputfile on commandline. # - Miscellaneous other tweaks. # use Socket; use POSIX qw(strftime); use Sys::Hostname; ## Define variables ## $logfile="/var/log/secure"; # Default input file $outputfile="/home/httpd/html/snort2html.html"; # Default output file. $hostname=hostname(); $MASQHOST=0; $time = strftime "%b %d at %H:%M", localtime; ## Check command line input ## $numArgs = $#ARGV +1; if ($numArgs == 1) { $logfile=$ARGV[0]; } elsif ($numArgs > 1) { $logfile=$ARGV[0]; $outputfile=$ARGV[1]; } ############################## # Main # ############################## &generatehtmlheader; # Call funtion to generate HTML header open(LOG,"$logfile") || die "Unable to open $logfile"; my @log = ; # Read whole file into big array close LOG; chomp @log; foreach (@log) { if ( ! /.*snort*/ ) # If it ain't got the word snort in it... { next; # ...get me another line. } if (/spp_portscan: PORTSCAN DETECTED/) { /(.*\s)(.*\s)(..:..:..\s)(.*).*\ssnort\[\d*\]:\sspp_portscan: PORTSCAN DETECTED from (\d+\.\d+\.\d+\.\d+)/; # month day timeofday $4 #Apr 5 10:32:31 stahlw06 snort[3577]: spp_portscan: PORTSCAN DETECTED from 134.169.69.224 #Sep 17 22:36:08 clgr003753 snort[25392]: spp_portscan: PORTSCAN DETECTED from 210.172.128.20 (STEALTH) $month = $1; $day = $2; $timeofday = $3; $hour = $3; $attack = "Portscan detected :"; $sourceip = $5; # $sourceport = ""; $targetip = $4; $targetport = ""; } elsif (/spp_portscan: End of portscan/) { /(.*\s)(.*\s)(..:..:..\s)(.*).*\ssnort\[\d*\]:\sspp_portscan: End of portscan from (\d+\.\d+\.\d+\.\d+)/; # month day timeofday $4 #Apr 5 10:32:57 stahlw06 snort[3577]: spp_portscan: End of portscan from 134.169.69.225 $month = $1; $day = $2; $timeofday = $3; $hour = $3; $attack = "End of portscan :"; $sourceip = $5; $sourceport = ""; $targetip = $4; $targetport = ""; } elsif (/spp_portscan: portscan status/) { /(.*\s)(.*\s)(..:..:..\s)(.*)\ssnort\[\d*\]:\sspp_portscan: portscan status from (\d+\.\d+\.\d+\.\d+): (\d+ )connections across (\d+ )hosts: TCP\((\d+)\), UDP\(( \d+)\)/; # month day timeofday $4 $5 $6 $7 $8 #Apr 5 10:32:39 stahlw06 snort[3577]: spp_portscan: portscan status from 134.169.69.224: 9 connections across 1 hosts: TCP(0), UDP(9) $month = $1; $day = $2; $timeofday = $3; $hour = $3; $attack = "Portscan status :"; $sourceip = $5; $sourceport = $6; $targetip = $4; $targetport = sprintf(":TCP \(%d\) UDP \(%d\)",$8,$9); } else { # normal regexp /(.*\s)(.*\s)(.*:..:..\s).*\s(snort.*:\s)(.*:\s)(.*\d\s)(.*\s)(.*)/; # Pattern matching against each line read from logfile # month day timeofday attack source target # Variables extracted from pattern matching above. $month = $1; $day = $2; $timeofday = $3; $hour = $3; $attack = $5; $sourceip = $6; $sourceport= $6; $targetip = $8; $targetport= $8; } # Get rid of unwanted characters $attack =~ s/://; $sourceip =~ s/:.*//; $hour =~ s/:.*//; if (!($sourceport =~ s/.*://)) {$sourceport = "-N/A-"}; $sourcehost=gethostbyaddr(inet_aton($sourceip), AF_INET); $targetip=~ s/:.*//; if (!($targetport =~ s/.*://)) {$targetport = "-N/A-"}; $targethost=gethostbyaddr(inet_aton($targetip), AF_INET); $searchattack=$attack; $searchattack=~ s/\s/+/g; chop $searchattack; &timecolor; &generatehtmlbody # Generate body of HTML from data read from snortlog } &generatehtmlfooter; # Generate footer of HTML chmod (0644, $outputfile); # Ensure that output file is world readable ############################################################# ####################Subroutines############################## ############################################################# sub generatehtmlheader { #Deletes old HTML file, creates new ones, and writes headings. unlink $outputfile; open (HTML, ">$outputfile"); print HTML "\n"; print HTML "\n"; print HTML "Hot dog! Jumping frog! Its an html2snort log! \n"; print HTML "\n"; print HTML "\n"; print HTML "

Snort log for $hostname

\n"; print HTML "\n"; print HTML "\n"; print HTML "\n"; print HTML "\n"; print HTML "\n"; print HTML "\n"; print HTML "\n"; print HTML "\n"; print HTML "\n"; print HTML "\n"; } sub timecolor { # Color code time of day according to daytime, evening, and nighttime. my $result = int($hour/6); if ($result == 0) {$hourcolor = "#000000"; } elsif ($result < 3) {$hourcolor = "#EEEE00"; } else {$hourcolor = "#FFCC00"; }; } sub generatehtmlbody { # Writes fields to html file. print HTML "\n"; print HTML "\n"; print HTML "\n"; print HTML "\n"; print HTML " \n"; if (($sourceport ne "-N/A-") && ($sourceport>61000) && ($sourceport<65096)) { $sourceportcolor="#006600"; $MASQHOST=1; } else {$sourceportcolor="#000000";} print HTML "\n"; print HTML "\n"; print HTML "\n"; print HTML "\n"; } sub generatehtmlfooter { # Writes end of HTML tags, and closes filehandle. print HTML "
DateTimeAttackSource HostSource PortTarget HostTarget Port
$month $day$timeofday \;$attack \;", $sourcehost || $sourceip, " \;$sourceport \;", $targethost || $targetip, " \;$targetport
\n"; if ( $MASQHOST ne "0" ) # Need to include masqsourceport explanation at end?? { print HTML "
DS =Possible masquerading host.
\n"; } print HTML "

\n"; print HTML "This page generated from snort logs on $time using snort2html<\/A> 1.5 by Dan Swan< /A>.
\n"; print HTML "\n"; print HTML "\n"; close (HTML); }