#!/usr/bin/perl # Fetches /var/log/secure from a list of hosts via ssh root@$host, # analyze them for failed attempts to log in as root with a password, # and print statistics about the failed attempts as well as all the # relevant log lines. # # Will detect and read /var/log/secure, /var/log/secure.#, # /var/log/secure-YYYYMMDD, /var/log/secure*gz (read with zcat), and # /var/log/secure*bz2 (read with bzcat). # # Specify --today to include today in the statistics. Otherwise today, # which is assumed to be incomplete, is ignored. # # Specify hosts to audit on the command line. use Date::Parse; use Getopt::Long; use POSIX 'strftime'; die if (! GetOptions("today" => \$today)); @hosts = @ARGV; foreach $host (@hosts) { print(STDERR "Doing $host\n"); die if (! defined($pid = open(SECURE, "-|"))); if (! $pid) { exec('ssh', "root\@$host", 'cat /var/log/secure; for file in /var/log/secure*[0-9]; do test -f $file && cat $file; done; for file in /var/log/secure*bz2; do test -f $file && bzcat $file; done; for file in /var/log/secure*gz; do test -f $file && zcat $file; done') or die; } while () { next if (! /^(... .. ..:..:..) .*: Failed password for root from (\S+)/); $ip = $2; $stamp = str2time($1); $date = strftime("%m/%d", localtime($stamp)); $by_host->{$host}->{$date}->{$ip} = 1; $by_date->{$date}->{$ip} = 1; push(@log_entries, [$stamp, $host, $_]); } } @dates = sort keys %{$by_date}; shift @dates; pop(@dates) if (! $today); &summarize("Overall", $by_date); print "\n"; foreach my $host (@hosts) { &summarize($host, $by_host->{$host}); } print "\n"; print "Log entries:\n"; print "\n"; print(map($_->[2], sort { $a->[0] <=> $b->[0] } @log_entries)); sub summarize { my($host, $ref) = @_; my($days) = scalar @dates; my($min, $max, $total, $avg, @counts); foreach my $date (@dates) { my $count = scalar keys %{$ref->{$date}}; $min = $count if (! defined($min)); $min = $count if ($count < $min); $max = $count if ($count > $max); $total += $count; push(@counts, $count); } $avg = sprintf("%.1f", $total/$days); print("$host: min/avg/max $min/$avg/$max, counts ($dates[0]-$dates[-1]) ", join(", ", @counts), "\n"); }