Fwd: windows logwatch update

"Kirk Bauer" <[email protected]>
Newsgroups gmane.comp.log.logwatch.devel
Message-ID <[email protected]>
Another update -- sorry for sending so many to the list, but I'm out of town
right now...

---------- Forwarded message ----------
From: Brian Kroth <[email protected]>
Date: Jun 14, 2007 9:17 AM
Subject: windows logwatch update
To: Kirk Bauer <[email protected]>

I suppose I should just add myself to the dev list, but I'm on too many
of those things at the moment.

Here's a mostly cosmetic update to the windows script I sent you
earlier.  It adds some header information to explain how the data is
displayed since it may not be obvious.

It also groups failed logins in two different ways - (Host, Account) or
(Account, Host).  I thought this might be a useful way to see that one
particular machine was getting hammered with failed logins.

Thanks again,
Brian
--
*******************************************************************************
Brian Kroth
Systems Administrator
UW Health Sciences Learning Center
750 Highland Avenue
Madison, WI  53705
608.261.1932
[email protected]

#!/usr/bin/perl
# windows
# 2007-06-04
# Brian Kroth
#
# This is a logwatch script that looks at a log file composed of windows
auth
# security logs counts the number of times a user failed to login and
# optionally the number times they succesfully logged in and some other
account
# creation/modification audits.
#
# See the following sites for event id documentation:
#
http://www.microsoft.com/technet/prodtechnol/windowsserver2003/technologies/security/bpactlck.mspx
# http://support.microsoft.com/?id=299475
# http://support.microsoft.com/?id=301677

use lib "/usr/share/logwatch/lib";
use Logwatch ':all';

my $detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0;

my ($month, $day, $time, $host, $process, $eventid, $msg);

# Loop through the given input and parse it first to make sure we need to,
# then to sort it into various categories.
while (defined($line = <STDIN>)) {

        ($month, $day, $time, $host, $process, $eventid, $msg) =
split(/\s+/, $line, 7);

        chomp($host);
        chomp($process);
        chomp($eventid);
        chomp($msg);

        if ($process =~ /security\[failure\]/) { # failure events

                # First count the number of failed logins - we always want
that.
                # Events 529 - 537, 539
                if (($eventid >= 529 && $eventid <= 537) || $eventid == 539
|| $eventid == 680) {
                        $msg =~ /(User Name|Logon
account):\s*(\S+)\s+.+(Address|Workstation( Name)?):\s*\\{0,2}(\S+)/;
                        # print "DEBUG Logon Failure: name:$2 source:$4\n";
                        $loginFailByAccount{$2}{$5}++;
                        $loginFailByHost{$5}{$2}++;
                }

                # IKE Failures: Events 544 - 547
                #elsif ($eventid >= 544 && $eventid <= 547 && $line =~
/some_meaningful_pattern/) {
                #}

                elsif ($eventid == 547) { # IKE security association
negotiation failed
                        $msg =~ /IKE Peer Addr\s+(\S+)\s+.+Failure
Reason:\s*(.+)\s+Extra Status:/;
                        #print "DEBUG IKE security association negotiation
failed: host:$host peer:$1 reason:$2\n";
                        $ikeSecNegFail{$host}{$1}{$2}++;
                }

                elsif ($eventid == 644) { # User Account Locked Out
                        $msg =~ /Target Account Name:\s*(\S+)\s+.+Caller
User Name:\s*(\S+)/;
                        #print "DEBUG User Account Locked Out: $1 on $2 by
$3\n";
                        $lockedOut{$host}{$1}{$2}++;
                }

                elsif ($eventid == 675 || $eventid == 676 || $eventid ==
677) { # Kerberos authentication failed
                        $msg =~ /User Name:\s*(\S+)\s+.+Client
Address:\s*(\S+)/;
                        #print "DEBUG Pre-Authentication failed: $1 on
$2\n";
                        #$krbAuthFail{$host}{$1}{$2}++;
                        $krbAuthFailByAccount{$1}{$2}++;
                        $krbAuthFailByHost{$2}{$1}++;
                }

                #elsif ($eventid == 681) { # Logon Failure - not used in
Windows 2003/XP
                #       $msg =~ /The logon to
account:\s*(\S+)\s+by:\s*(\S+)\s+from workstation:\s*(\S+)\s+failed/;
                #       print "DEBUG Logon Failure to $1 by $2 from $3\n";
                #       $logonFailure{$1}{$2}{$3}++;
                #}

                elsif ($eventid == 861) { # The Windows Firewall has
detected an application listenin for incomming traffic.
                        $msg =~ /Path:\s*(\S+)\s+.+User
account:\s*(\S+)\s+.+IP protocol:(\S+)\s+Port
number:\s*(\S+)\s+Allowed:\s*(\S+)/;
                        #print "DEBUG Server Application Firewalled: path:$1
account:$2 port:$3 $4 allowed:$5\n";
                        $firewall{$host}{$2}{$1}{$3}{$4}{$5}++;
                }

                else { # unmatched catch all
                        chomp($msg);
                        $unmatchedFail{$eventid . " " . $msg}++;
                }
        }

        elsif ($detail > 3 && $process =~ /security\[success\]/) { # success
events

                if ($eventid == 528 || $eventid == 540 || $eventid == 680) {
# Successful Logon
                        $msg =~ /(User Name|Logon account|Account
Name):\s*(\S+)\s+.+(Address|Workstation( Name)?):\s*\\{0,2}(\S+)/;
                        if ($2 !~ /^-|\S+\$$/) { # ignore machines and
anonymous
                                #print "DEBUG Logon Success name:$2
source:$5\n";
                                $loginSuccess{$2}{$5}++;
                        }
                }

                elsif ($eventid == 517) { # Audit log was cleared.
                        $msg =~ /Primary User Name:\s*(\S+)\s+.*Client User
Name:\s*(\S+)/;
                        # print "DEBUG Audit log cleared: host:$host
primary:$1 client:$2\n";
                        $auditLogCleared{$host}{$1}{$2}++;
                }

                elsif ($eventid == 608) { # User Right Assigned
                        $msg =~ /User Right:\s*(\S+)\s+Assigned
To:\s*(\S+)\s+Assigned By:\s+User Name:\s*(\S+)/;
                        # print "DEBUG Rights Added: right:$1 to:$2
by:$3\n";
                        $rightsAdded{$host}{$3}{$2}{$1}++;
                }
                elsif ($eventid == 609) { # User Right Removed
                        $msg =~ /User Right:\s*(\S+)\s+Removed
From:\s*(\S+)\s+Removed By:\s+User Name:\s*(\S+)/;
                        # print "DEBUG Rights Removed: right:$1 from:$2
by:$3\n";
                        $rightsRemoved{$host}{$3}{$2}{$1}++;
                }

                elsif ($eventid == 610) { # New Trusted Domain
                        $msg =~ /New Trusted Domain\s+Domain(
Name)?:\s*(\S+)\s+.*Established By:\s+User Name:\s*(\S+)/;
                        # print "DEBUG New Trusted Domain: domain:$2 user:$3
host:$host\n";
                        $newDomainTrust{$host}{$2}{$3}++;
                }
                elsif ($eventid == 611) { # Removing Trusted Domain
                        $msg =~ /Removing Trusted Domain\s+Domain(
Name)?:\s*(\S+)\s+.*Established By:\s+User Name:\s*(\S+)/;
                        # print "DEBUG New Trusted Domain: domain:$2 user:$3
host:$host\n";
                        $rmDomainTrust{$host}{$2}{$3}++;
                }

                elsif ($eventid == 612) { # Audit Policy Changed
                        $msg =~ /Changed By:\s+User Name:\s*(\S+)/;
                        # print "DEBUG Audit Policy Changed by $1 on
$host\n";
                        $auditPolChange{$host}{$1}++;
                }

                # Group all account types together - should be clear what's
what.
                elsif ($eventid == 624 || $eventid == 631 || $eventid == 635
|| $eventid == 645
                        || $eventid == 653 || $eventid == 658 || $eventid ==
663) { # Account Created

                        $msg =~ /New Account Name:\s*(\S+)\s+.*Caller User
Name:\s*(\S+)/;
                        #print "DEBUG Account Created: $1 by $2 on $host\n";
                        $newAccount{$host}{$2}{$1}++;
                }
                elsif ($eventid == 625) { # User Account Type Change
                        $msg =~ /Target Account Name:\s*(\S+)\s+.+New
Type:\s*(\S+)\s*Caller User Name:\s*(\S+)/;
                        # print "DEBUG User Account Type Change: $1 to $2 by
$3 on $host\n";
                        $accountTypeChange{$host}{$3}{$1}{$2}++;
                }
                elsif ($eventid == 626) { # User Account Enabled
                        $msg =~ /Target Account Name:\s*(\S+)\s+.+Caller
User Name:\s*(\S+)/;
                        # print "DEBUG User Account Enabled: $1 by $2 on
$host\n";
                        $accountEnabled{$host}{$2}{$1}++;
                }
                elsif ($eventid == 627) { # Change Password Attempt
                        $msg =~ /Target Account Name:\s*(\S+)\s+.+Caller
User Name:\s*(\S+)/;
                        # print "DEBUG Change Password Attempt: $1 by $2 on
$host\n";
                        $changePasswordAttempt{$host}{$2}{$1}++;
                }
                elsif ($eventid == 628) { # User Account password set
                        $msg =~ /Target Account Name:\s*(\S+)\s+.+Caller
User Name:\s*(\S+)/;
                        # print "DEBUG User Account password set: $1 by $2
on $host\n";
                        $passwordSet{$host}{$2}{$1}++;
                }
                elsif ($eventid == 630 || $eventid == 634 || $eventid == 638
|| $eventid == 647
                        || $eventid == 652 || $eventid == 657 || $eventid ==
662 || $eventid == 667) { # User Account Deleted

                        $msg =~ /Target Account Name:\s*(\S+)\s+.+Caller
User Name:\s*(\S+)/;
                        # print "DEBUG Account Deleted: $1 by $2 on
$host\n";
                        $accountDeleted{$host}{$2}{$1}++;
                }

                # Note: This doesn't distinguish between Global and Local
Groups
                elsif ($eventid == 632 || $eventid == 636 || $eventid == 650
|| $eventid == 655
                        || $eventid == 660 || $eventid == 665) { # Group
Member Added

                        $msg =~ /Member Name:\s*(\S+)\s+.+Target Account
Name:\s*(\S+)\s+.+Caller User Name:\s*(\S+)/;
                        # print "DEBUG Group Member Added: $1 to $2 by $3 on
$host\n";
                        $groupMemberAdded{$host}{$2}{$3}{$1}++;
                }
                elsif ($eventid == 633 || $eventid == 637 || $eventid == 651
|| $eventid == 656
                        || $eventid == 661 || $eventid == 666) { # Group
Member Removed

                        $msg =~ /Member Name:\s*(\S+)\s+.+Target Account
Name:\s*(\S+)\s+.+Caller User Name:\s*(\S+)/;
                        #print "DEBUG Group Member Removed: $1 to $2 by $3
on $host\n";
                        $groupMemberRemoved{$host}{$2}{$3}{$1}++;
                }
                elsif ($eventid == 639 || $eventid == 641 || $eventid == 642
|| $eventid == 646 || $eventid == 649
                        || $eventid == 654 || $eventid == 659 || $eventid ==
664 || $eventid == 668) { # Account Changed

                        $msg =~ /Target Account Name:\s*(\S+)\s+.+Caller
User Name:\s*(\S+)/;
                        #print "DEBUG Account Changed: $1 by $2 on $host\n";
                        $accountChanged{$host}{$2}{$1}++;
                }

                elsif ($eventid == 643) { # Domain Policy Changed
                        $msg =~ /Domain Policy Changed:\s*(.+)
modified.+Caller User Name:\s*(\S+)/;
                        #print "DEBUG Domain Policy Changed: $2 on $host to
$1\n";
                        $domainPolicyChanged{$host}{$2}{$1}++;
                }

                elsif ($detail > 5 && $eventid == 672) { # Authentication
Ticket Granted
                        $msg =~ /User Name:\s*(\S+)\s+.+Service
Name:\s*(\S+)\s+.+Client Address:\s*(\S+)/;
                        #print "DEBUG TGT Granted to $1 for $2 from $3\n";
                        $tgtGranted{$host}{$1}{$2}{$3}++;
                }
                elsif ($detail > 5 && $eventid == 673) { # Service Ticket
Granted
                        $msg =~ /User Name:\s*(\S+)\s+.+Service
Name:\s*(\S+)\s+.+Client Address:\s*(\S+)/;
                        #print "DEBUG SGT Granted to $1 for $2 from $3\n";
                        $sgtGranted{$host}{$1}{$2}{$3}++;
                }
                elsif ($detail > 5 && $eventid == 674) { # Ticket Granted
Renewed
                        $msg =~ /User Name:\s*(\S+)\s+.+Service
Name:\s*(\S+)\s+.+Client Address:\s*(\S+)/;
                        #print "DEBUG Ticket Renewal granted to $1 for $2
from $3\n";
                        $renewed{$host}{$1}{$2}{$3}++;
                }
        }

}


# Always print login failures grouped by name and host in that order.
if (keys %loginFailByAccount) {
        printLevel2("Windows Failed Logins by Account, Host",
\%loginFailByAccount);
}
if (keys %loginFailByHost) {
        printLevel2("Windwos Failed Logins by Host, Account",
\%loginFailByHost);
}

if (keys %krbAuthFailByAccount) {
        printLevel2("Kerberos Authentication Failures by Account, Host",
\%krbAuthFailByAccount);
}

if (keys %krbAuthFailByHost) {
        printLevel2("Kerberos Authentication Failures by Host, Account",
\%krbAuthFailByHost);
}

if (keys %lockedOut) {
        printLevel3("Account Locked Out by Host, Target, Caller",
\%lockedOut);
}

if (keys %ikeSecNegFail) {
        printLevel3("IKE Security Association Negotiation Failed by Host,
Peer, Reason", \%ikeSecNegFail);
}

if (keys %unmatchedFail) {
        print "\t---- Unmatched Failure Audits ----\n\n";
        foreach $msg (keys %unmatchedFail) {
                print "\t" . $unmatchedFail{$msg} . " Time(s):  $msg\n";
        }
}

# Start printing some other optional data like login successes, account
creation/modification audits, etc.
if ($detail > 3) {
        if (keys %loginSuccess) {
                printLevel2("Windows Successful Logins by Account, Host",
\%loginSuccess);
        }

        if ($detail > 5) {
                if (keys %tgtGranted) {
                        printLevel4("TGT Granted by Host, Account, Service,
Client Addr", \%tgtGranted);
                }
                if (keys %sgtGranted) {
                        printLevel4("SGT Granted by Host, Account, Service,
Client Addr", \%sgtGranted);
                }
                if (keys %renewed) {
                        printLevel4("Ticket Renewed by Host, Account,
Service, Client Addr", \%renewed);
                }
        }

        if (keys %auditLogCleared) {
                printLevel3("Audit Log Cleared by Host, Primary Account,
Client Account", \%auditLogCleared);
        }

        if (keys %rightsAdded) {
                printLevel4("User Rights Added by Host, Modifier, Account,
Right", \%rightsAdded);
        }
        if (keys %rightsRemoved) {
                printLevel4("User Rights Removed by Host, Modifier, Account,
Right", \%rightsRemoved);
        }

        if (keys %newDomainTrust) {
                printLevel3("New Domain Trust by Host, Domain, Modifier",
\%newDomainTrust);
        }
        if (keys %rmDomainTrust) {
                printLevel3("Domain Trust Removed by Host, Domain,
Modifier", \%rmDomainTrust);
        }

        if (keys %auditPolChange) {
                printLevel2("Audit Policy Changed by Host, Modifier",
\%auditPolChange);
        }

        if (keys %newAccount) {
                printLevel3("New Accounts by Host, Modifier, Account",
\%newAccount);
        }
        if (keys %accountTypeChange) {
                printLevel4("Account Type Changed by Host, Modifier,
Account, Type", \%accountTypeChange);
        }
        if (keys %accountEnabled) {
                printLevel3("Account Enabled by Host, Modifier, Account",
\%accountEnabled);
        }
        if (keys %changePasswordAttempt) {
                printLevel3("Change Password Attempt by Host, Modifier,
Account", \%changePasswordAttempt);
        }
        if (keys %passwordSet) {
                printLevel3("Password Set by Host, Modifier, Account",
\%passwordSet);
        }
        if (keys %accountDeleted) {
                printLevel3("Account Deleted by Host, Modifier, Account",
\%accountDeleted);
        }

        if (keys %groupMemberAdded) {
                printLevel4("Group Member Added by Host, Group, Modifier,
Account", \%groupMemberAdded);
        }
        if (keys %groupMemberRemoved) {
                printLevel4("Group Member Removed by Host, Group, Modifier,
Account", \%groupMemberRemoved);
        }
        if (keys %accountChanged) {
                printLevel3("Account Changed by Host, Modifier, Account",
\%accountChanged);
        }

        if (keys %domainPolicyChanged) {
                printLevel3("Domain Policy Changed by Host, Modifier,
Change", \%domainPolicyChanged);
        }
}



# Prints a hash that's two levels deep in a generic hierarchical manor
sub printLevel2 {
        my $msg = $_[0];
        my %data = %{$_[1]};

        print "\n\t---- $msg ----\n\n";
        foreach $first (sort(keys %data)) {
                $total = 0;
                foreach $second (keys %{$data{$first}}) {
                        $total += $data{$first}{$second};
                }

                print "\t" . LookupIP($first) . "  $total Time(s)\n";
                foreach $second (sort(keys %{$data{$first}})) {
                        print  "\t\t" . LookupIP($second) . "  " .
$data{$first}{$second} . " Time(s)\n";
                }
                print "\n";
        }
}

# Prints a hash that's three levels deep in a generic hierarchical manor
sub printLevel3 {
        my $msg = $_[0];
        my %data = %{$_[1]};

        print "\n\t---- $msg ----\n\n";
        foreach $first (sort(keys %data)) {
                $first_total = 0;
                foreach $second (keys %{$data{$first}}) {
                        $second_total{$second} = 0;
                        foreach $third (keys %{$data{$first}{$second}}) {
                                $second_total{$second} +=
$data{$first}{$second}{$third};
                        }
                        $first_total += $second_total{$second};
                }

                print "\t" . LookupIP($first) . ":  $first_total Time(s)\n";
                foreach $second (sort(keys %{$data{$first}})) {
                        print "\t\t" . LookupIP($second) .
":  $second_total{$second} Time(s)\n";
                        foreach $third (sort(keys
%{$data{$first}{$second}})) {
                                print "\t\t\t" . LookupIP($third) .
"  $data{$first}{$second}{$third} Time(s)\n";
                        }
                }
                print "\n";
        }
}

# Prints a hash that's four levels deep in a generic hierarchical manor
sub printLevel4 {
        my $msg = $_[0];
        my %data = %{$_[1]};

        print "\n\t---- $msg ----\n\n";
        foreach $first (sort(keys %data)) {
                $first_total = 0;
                foreach $second (keys %{$data{$first}}) {
                        $second_total{$second} = 0;
                        foreach $third (keys %{$data{$first}{$second}}) {
                                $third_total{$second}{$third} = 0;
                                foreach $fourth (keys
%{$data{$first}{$second}{$third}}) {
                                        $third_total{$second}{$third} +=
$data{$first}{$second}{$third}{$fourth};
                                }
                                $second_total{$second} +=
$third_total{$second}{$third};
                        }
                        $first_total += $second_total{$second};
                }

                print "\t" . LookupIP($first) . ":  $first_total Time(s)\n";
                foreach $second (sort(keys %{$data{$first}})) {
                        print "\t\t" . LookupIP($second) .
":  $second_total{$second} Time(s)\n";
                        foreach $third (sort(keys
%{$data{$first}{$second}})) {
                                print "\t\t\t" . LookupIP($third) .
":  $third_total{$second}{$third} Time(s)\n";
                                foreach $fourth (sort(keys
%{$data{$first}{$second}{$third}})) {
                                        print "\t\t\t\t" . LookupIP($fourth)
. "  $data{$first}{$second}{$third}{$fourth} Time(s)\n";
                                }
                        }
                }
                print "\n";
        }
}

exit(0);




-- 
Kirk Bauer <[email protected]>
http://linux.kaybee.org | www.autorpm.org | www.logwatch.org

_______________________________________________
Logwatch-Devel mailing list
[email protected]
http://www2.list.logwatch.org:81/mailman/listinfo/logwatch-devel
smime.p7s (application/x-pkcs7-signature, 3.3 KB) - not displayed
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.