#!/usr/bin/perl use strict; use Net::SMTP; use File::Glob; use POSIX qw(strftime); # Written by Nathan Shanks v.06 # Mike Wimpy helped a ton with this script! Thanks! # Mail Setup my $mailserver=""; my $smtpto='reports@dshield.org'; my $smtpfrom=''; my ($smtp, @ok_addr); # Make sure to include your user ID my $userID = ""; my @fileList = File::Glob::bsd_glob("/var/log/security.*.bz2"); push( @fileList, "/var/log/security" ); # Misc options my $data = "/var/log/security"; my $lastTimeStamp="0"; my $lastTimeStampFile="/tmp/dshield_lastrun.tmp"; # IP Addresses you want to exclude my @exip; push( @exip, "10.0.0.0/8" ); ; # Don't touch these values my $year = strftime("%Y", localtime); # Taking the time zone off the local system my $timezone = substr( strftime("%z", localtime), 0, 3 ) . ":" . substr( strftime("%z", localtime), 3, 2 ); my @data; my ($month2,$day2,$time2); my ($month,$day,$time,$messsage,$rule,$action,$proto,$srcip,$srcport,$destip,$destport); my (%hash1, %hash2, %month); $month{Jan} = "01"; $month{Feb} = "02"; $month{Mar} = "03"; $month{Apr} = "04"; $month{May} = "05"; $month{Jun} = "06"; $month{Jul} = "07"; $month{Aug} = "08"; $month{Sep} = "09"; $month{Oct} = "10"; $month{Nov} = "11"; $month{Dec} = "12"; # Check to see the last file I sent if (-e $lastTimeStampFile) { open (DSHIELD, $lastTimeStampFile) or die "CAN NOT OPEN OR CREATE $lastTimeStampFile ($!)"; while () { my $line = $_; $line =~ s/\n//g; if( length( $line ) == 14 ) { $lastTimeStamp = $line; } } close( DSHIELD ); } open (EXTRA, ">>/tmp/dshieldmissed.tmp") or die "UNABLE TO OPEN $data ($!)"; foreach my $curFile ( @fileList ) { my $modtime = (stat($curFile))[9]; my $modtimeString = strftime("%Y%m%d%H%M%S", localtime($modtime)); if( $modtimeString gt $lastTimeStamp ) { $data = $curFile; # Open the security log (use the $data to declare static log) if( $data =~ /.bz2/ ) { open( SECURITY, "-|", "bzcat $data" ); } else { open (SECURITY, "$data") or die "UNABLE TO OPEN $data ($!)"; } print "Reading $data:"; MAINLOOP: while () { # The big regular expression to pull all the data out if (($month,$day,$time,$messsage,$rule,$action,$proto,$srcip,$srcport,$destip,$destport)= /(\w{3})\s+(\d+)\s+(\d{2}:\d{2}:\d{2})\s+(\w+\s+\w+:\s+\w{4}:)\s(\d+)\s+(\w+)\s+(\w+)\s(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}):(\d{1,5})\s+(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}):(\d{1,5})\s+(?:in|out)\s+via\s+\w{2,3}\d+/) { if ($action =~ /deny/i ) #only send denies { foreach my $subnet( @exip )# Remove IP's you don't want to include { #print("ipInSubnet( $srcip, $subnet ) || ipInSubnet( $destip, $subnet )\n"); if( ipInSubnet( $srcip, $subnet ) == 1 || ipInSubnet( $destip, $subnet ) == 1 ) { #print("Found $srcip or $destip in $subnet. Skipping"); next MAINLOOP; } } if( length($day) == 1 ) { $day = "0"."$day"; } my $curTimeStamp="$year$month{$month}$day$time"; $curTimeStamp =~ s/://g; if ( $curTimeStamp le $lastTimeStamp ) { #do nothing } else { # check if its a duplicate if not store it and if it is increase the count if ($hash1{$proto,$srcip,$srcport,$destip,$destport} eq 0) { $hash1{$proto,$srcip,$srcport,$destip,$destport} = 1; $hash2{$proto,$srcip,$srcport,$destip,$destport} = "$year-$month{$month}-$day $time $timezone\t$userID\t$hash1{$proto,$srcip,$srcport,$destip,$destport}\t$srcip\t$srcport\t$destip\t$destport\t$proto"; } else { $hash1{$proto,$srcip,$srcport,$destip,$destport}++; $hash2{$proto,$srcip,$srcport,$destip,$destport} = "$year-$month{$month}-$day $time $timezone\t$userID\t$hash1{$proto,$srcip,$srcport,$destip,$destport}\t$srcip\t$srcport\t$destip\t$destport\t$proto"; } } } } elsif (($month,$day,$time,$messsage,$rule,$action,$proto,$srcport,$destport,$srcip,$destip)= /(\w{3})\s+(\d+)\s+(\d{2}:\d{2}:\d{2})\s+(\w+\s+\w+:\s+\w{4}:)\s+(\d+)\s+(\w+)\s+(ICMP):(\d+).(\d+)\s+(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})\s+(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})\s+(?:in|out)\s+via\s+\w{2,3}\d+/) { if ($action =~ /deny/i )#only send denies { foreach my $subnet( @exip )# Remove IP's you don't want to include { #print("ipInSubnet( $srcip, $subnet ) || ipInSubnet( $destip, $subnet )\n"); if( ipInSubnet( $srcip, $subnet ) == 1 || ipInSubnet( $destip, $subnet ) == 1 ) { #print("Found $srcip or $destip in $subnet. Skipping"); next MAINLOOP; } } if( length($day) == 1 ) { $day = "0"."$day"; } my $curTimeStamp="$year$month{$month}$day$time"; $curTimeStamp =~ s/://g; if ( $curTimeStamp le $lastTimeStamp ) { #do nothing } else { # check if its a duplicate if not store it and if it is increase the count if ($hash1{$proto,$srcip,$srcport,$destip,$destport} eq 0) { $hash1{$proto,$srcip,$srcport,$destip,$destport} = 1; $hash2{$proto,$srcip,$srcport,$destip,$destport} = "$year-$month{$month}-$day $time $timezone\t$userID\t$hash1{$proto,$srcip,$srcport,$destip,$destport}\t$srcip\t$srcport\t$destip\t$destport\t$proto"; } else { $hash1{$proto,$srcip,$srcport,$destip,$destport}++; $hash2{$proto,$srcip,$srcport,$destip,$destport} = "$year-$month{$month}-$day $time $timezone\t$userID\t$hash1{$proto,$srcip,$srcport,$destip,$destport}\t$srcip\t$srcport\t$destip\t$destport\t$proto"; } } } } else { #print EXTRA "$_\n"; } } print "done\n"; close SECURITY; } } print "Producing Output:"; open (OUTPUT, "> /tmp/output.tmp") or die "CAN NOT OPEN OR CREATE output.tmp ($!)"; # Write your output to a file that can be mailed foreach (values %hash2) { push(@data, "$_\n"); print OUTPUT "$_\n"; } close(OUTPUT); close(EXTRA); print "done\n"; if (@data ne 0) { print "Sendmail Email:"; &mail; print "done\n"; } else { print "No data to send email not sent.\n"; } open (DSHIELD, ">$lastTimeStampFile") or die "CAN NOT OPEN OR CREATE $lastTimeStampFile ($!)"; $lastTimeStamp = "$year$month{$month}$day$time"; $lastTimeStamp =~ s/://g; print(DSHIELD "$lastTimeStamp\n"); close( DSHIELD ); sub mail { # Define the Subject line my $subject="FORMAT DSHIELD USERID $userID TZ $timezone"; # Build a mail server connection $smtp = Net::SMTP->new($mailserver,Timeout=>60); # From and to $smtp->mail($smtpfrom); $smtp->to($smtpto); @ok_addr = $smtp->recipient($smtpto, {SkipBad=>1}); # Plugin the data and transmit $smtp->data(); $smtp->datasend("From: $smtpfrom\n"); $smtp->datasend("Subject: $subject\n"); $smtp->datasend(@data); $smtp->dataend(); $smtp->quit; } sub ipInSubnet { my $ip = shift; my $subnet = shift; my $subnetBin; my $ipBin; my $mask; my $match = 0; if( $subnet =~ /(\d{1,3}).(\d{1,3}).(\d{1,3}).(\d{1,3})\/(\d+)/ ) { $subnetBin = $1<<24 | $2<<16 | $3<<8 | $4; $mask = 0xFFFFFFFF << (32-$5); $subnetBin &= $mask; #printf("0x%.8X\n", $subnetBin); } if( $ip =~ /(\d{1,3}).(\d{1,3}).(\d{1,3}).(\d{1,3})/ ) { $ipBin = $1<<24 | $2<<16 | $3<<8 | $4; $ipBin &= $mask; #printf("0x%.8X\n", $ipBin); } if( $subnetBin == $ipBin ) { #print("Match!\n"); $match =1; } return $match; }