#!/usr/bin/perl -w # # Snort2HTML 1.6 by Dan Swan, Nov 12, 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 hourly, # 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". # # You must be using snort with the "-s" option, to ensure that the # alerts are being logged in a parsable format to /var/log/secure. # The alerts logged by default to /var/log/snort/snort.alerts are # insufficient. # # TODO: -Display service on Target port # -More color coding of source port (suggestions welcome!) # -Dynamic sorting by clicking on column header. # -Options 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-friendly. # Please send them to swan_daniel@hotmail.com # # # TROUBLESHOOTING: # 1) Download latest version from http://www.geocities.com/swan_daniel/snort2html.txt # 2) Read the above comments again. # 3) If you are a getting a lot of "Use of uninitialized value" errors, it is likely because] # you are not using snort with the "-s" flag, or are pointing at the wrong logfile. # 4) If you are getting a few "Use of uninitialized value" errors, your nameserver is not # set up correctly, and portscanning hosts are not being resolved properly. To fix this, # make sure you specify a domain in your /etc/resolv.conf. # 5) If you have done the above, and are still having troubles, please mail me at # swan_daniel@hotmail.com, along with your snort2html output, your alerts file, # and a description of the problem you are having, and we'll get you sorted out. # # 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 snort 1.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. # # 1.6 November 12, 2000 # - Changed "html2snort" in title bar to "snort2html". Thanks to the # many people who pointed out my late night brainfart. # - Beefed up documentation to address common issues. # - Added the option to disable DNS lookups. # - Added the option to hide targethost. # - Added the option to print debugging output to STDOUT. # - Corrected a regex problem w/ Arin lookups of some ICMP # generated alerts as reported by Claus Jeppesen. # # Options # Set disableDNS to 1 to disable DNS lookups. This is recommended on # high traffic sites, as the lookups take a lot of time and generate a # lot of traffic. Also, outputting just IP's instead of hostnames # decreases the horizontal size of output, and may be useful for those # with# small screen sizes/resolutions. $disableDNS=0; # Set disableshowtarget to 1 to disable the showing of the target host. # This is useful for those who have smaller screen sizes/resolutions # and want to decrease the horizontal size of the output. $disableshowtarget=0; # Enable this option to print out data on the command line as it is # read from the snort alert file. This will help pin down which # alerts are causing "Uninitialized value" errors. $debug=0; #Use Libraries 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 debugging enabled print data read from alert file if ($debug==1) {print $_,"\n\n";} 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; $targetip = $4; $attack = "Portscan detected :"; $sourceip = $5; $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; $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; $targetip = $4; $attack = "Portscan status :"; $sourceip = $5; $sourceport = $6; $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; $attack = $5; $sourceip = $6; $sourceport= $6; $targetip = $8; $targetport= $8; } # Get rid of unwanted characters $attack =~ s/://; $sourceip =~ s/:.*//; $sourceip =~ s/\s//; $hour= $timeofday; $hour =~ s/:.*//; if (!($sourceport =~ s/.*://)) {$sourceport = "-N/A-"}; if ($disableDNS != 1) { $sourcehost=gethostbyaddr(inet_aton($sourceip), AF_INET); } $targetip=~ s/:.*//; if (!($targetport =~ s/.*://)) {$targetport = "-N/A-"}; if ($disableDNS != 1) { $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 a snort2html 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"; if ($disableshowtarget !=1){ 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"; if ($disableshowtarget !=1){ 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.6 by Dan Swan.
\n"; print HTML "\n"; print HTML "\n"; close (HTML); }