|
0 |
#!/usr/bin/perl -w
|
|
1 |
##########################################################################
|
|
2 |
# $Id: mod_security2, v 1.0.1 2013/01/11
|
|
3 |
##########################################################################
|
|
4 |
#
|
|
5 |
# Revision 1.0.1 2013/01/11
|
|
6 |
# fixed problem with uninitialized values #6
|
|
7 |
#
|
|
8 |
##########################################################################
|
|
9 |
# This script is written an maintained by:
|
|
10 |
# Torben Hansen <derhansen@gmail.com>
|
|
11 |
#
|
|
12 |
# To send comments, suggestions, bugreports, etc, please use:
|
|
13 |
# https://github.com/derhansen/logwatch-modsec2
|
|
14 |
##########################################################################
|
|
15 |
|
|
16 |
##########################################################################
|
|
17 |
# Copyright © 2013 Torben Hansen <derhansen@gmail.com>
|
|
18 |
#
|
|
19 |
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
20 |
# copy of this software and associated documentation files (the
|
|
21 |
# “Software”), to deal in the Software without restriction, including
|
|
22 |
# without limitation the rights to use, copy, modify, merge, publish,
|
|
23 |
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
24 |
# permit persons to whom the Software is furnished to do so, subject to
|
|
25 |
# the following conditions:
|
|
26 |
#
|
|
27 |
# The above copyright notice and this permission notice shall be included
|
|
28 |
# in all copies or substantial portions of the Software.
|
|
29 |
#
|
|
30 |
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
31 |
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANT-
|
|
32 |
# ABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
|
33 |
# EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
34 |
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
35 |
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
|
36 |
# THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
37 |
#
|
|
38 |
##########################################################################
|
|
39 |
|
|
40 |
use Logwatch ':dates';
|
|
41 |
|
|
42 |
# Disable warnings about unused variables
|
|
43 |
no warnings qw(once);
|
|
44 |
|
|
45 |
my $Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0;
|
|
46 |
my $Debug = $ENV{'LOGWATCH_DEBUG'} || 0;
|
|
47 |
my $SearchDate = TimeFilter('%d/%b/%Y:%H:%M:%S');
|
|
48 |
my $within_range = 0;
|
|
49 |
|
|
50 |
my %tmpEntry = ();
|
|
51 |
my $count = 0;
|
|
52 |
|
|
53 |
my %messages = ();
|
|
54 |
my %topips = ();
|
|
55 |
my %toprules = ();
|
|
56 |
|
|
57 |
my $check = 0;
|
|
58 |
my $option = '';
|
|
59 |
|
|
60 |
if ( $Debug >= 5 ) {
|
|
61 |
print STDERR "\n\nDEBUG MODE \n\n";
|
|
62 |
}
|
|
63 |
|
|
64 |
# Initialize array
|
|
65 |
$tmpEntry{$count}{"action"} = "";
|
|
66 |
$tmpEntry{$count}{"hostname"} = "";
|
|
67 |
$tmpEntry{$count}{"message"} = "";
|
|
68 |
$tmpEntry{$count}{"ruleid"} = "";
|
|
69 |
|
|
70 |
while (defined($ThisLine = <STDIN>)) {
|
|
71 |
chomp($ThisLine);
|
|
72 |
|
|
73 |
# Reset $check if line starts with two dashes
|
|
74 |
if ( $ThisLine =~ /-[A-Z]--/ ) {
|
|
75 |
$check = 0;
|
|
76 |
$option = "";
|
|
77 |
}
|
|
78 |
|
|
79 |
if ($check == 1) {
|
|
80 |
if ($option eq "audit-log-header") {
|
|
81 |
($timestamp, $transactionID, $sourceIP, $sourcePort, $destIP, $destPort ) = ($ThisLine =~ /\[(.*?)\] (.*?) (.*?) (.*?) (.*?) (.*?)$/ );
|
|
82 |
|
|
83 |
$tmpEntry{$count}{"timestamp"} = $timestamp;
|
|
84 |
$tmpEntry{$count}{"sourceIp"} = $sourceIP;
|
|
85 |
$tmpEntry{$count}{"sourcePort"} = $sourcePort;
|
|
86 |
$tmpEntry{$count}{"destIp"} = $destIP;
|
|
87 |
$tmpEntry{$count}{"destPort"} = $destPort;
|
|
88 |
|
|
89 |
if ( $Debug >= 5 ) {
|
|
90 |
print STDERR "\n";
|
|
91 |
print STDERR "DATE: " . $timestamp . "\n";
|
|
92 |
print STDERR "FROM: ". $sourceIP . ":" . $sourcePort . "\n";
|
|
93 |
print STDERR "TO: ". $destIP . ":" . $destPort . "\n";
|
|
94 |
}
|
|
95 |
}
|
|
96 |
|
|
97 |
if ($option eq "request-header") {
|
|
98 |
if ( ($method, $requestUri) = ($ThisLine =~ /^(POST|GET) (.*?)$/) ) {
|
|
99 |
$tmpEntry{$count}{"method"} = $method;
|
|
100 |
$tmpEntry{$count}{"uri"} = $requestUri;
|
|
101 |
|
|
102 |
if ( $Debug >= 5 ) {
|
|
103 |
print STDERR "METHOD: " . $method . "\n";
|
|
104 |
print STDERR "URI: " . $requestUri . "\n";
|
|
105 |
}
|
|
106 |
}
|
|
107 |
elsif ( ($hostname) = ($ThisLine =~ /^Host: (.*?)$/) ) {
|
|
108 |
$tmpEntry{$count}{"hostname"} = $hostname;
|
|
109 |
|
|
110 |
if ( $Debug >= 5 ) {
|
|
111 |
print STDERR "HOST: " . $hostname . "\n";
|
|
112 |
}
|
|
113 |
}
|
|
114 |
}
|
|
115 |
if ($option eq "audit-log-trailer") {
|
|
116 |
if ( $ThisLine =~ /^Message:/ ) {
|
|
117 |
if ( ($ruleId) = ($ThisLine =~ /\[id \"(.*?)\"\]/) ) {
|
|
118 |
if ( $Debug >= 5 ) {
|
|
119 |
print STDERR "Rule ID: " . $ruleId. "\n";
|
|
120 |
}
|
|
121 |
}
|
|
122 |
if ( ($msg) = ($ThisLine =~ /\[msg \"(.*?)\"\]/) ) {
|
|
123 |
if ( $Debug >= 5 ) {
|
|
124 |
print STDERR "Message: " . $msg. "\n";
|
|
125 |
}
|
|
126 |
}
|
|
127 |
$tmpEntry{$count}{"ruleid"} = $ruleId;
|
|
128 |
$tmpEntry{$count}{"message"} = $msg;
|
|
129 |
}
|
|
130 |
|
|
131 |
if ( ($action) = ($ThisLine =~ /^Action: (.*?)$/) ) {
|
|
132 |
$tmpEntry{$count}{"action"} = $action;
|
|
133 |
if ( $Debug >= 5 ) {
|
|
134 |
print STDERR "Action: " . $action. "\n";
|
|
135 |
}
|
|
136 |
}
|
|
137 |
if ( ($engineMode) = ($ThisLine =~ /^Engine-Mode: (.*?)$/) ) {
|
|
138 |
$tmpEntry{$count}{"engine"} = $engineMode;
|
|
139 |
if ( $Debug >= 5 ) {
|
|
140 |
print STDERR "Engine mode: " . $engineMode. "\n";
|
|
141 |
}
|
|
142 |
}
|
|
143 |
}
|
|
144 |
}
|
|
145 |
|
|
146 |
if ( $ThisLine =~ /-A--/ ) {
|
|
147 |
$check = 1;
|
|
148 |
$option = "audit-log-header";
|
|
149 |
}
|
|
150 |
elsif ( $ThisLine =~ /-B--/ ) {
|
|
151 |
$check = 1;
|
|
152 |
$option = "request-header";
|
|
153 |
}
|
|
154 |
elsif ( $ThisLine =~ /-H--/ ) {
|
|
155 |
$check = 1;
|
|
156 |
$option = "audit-log-trailer";
|
|
157 |
}
|
|
158 |
elsif ( $ThisLine =~ /-Z--/ ) {
|
|
159 |
$check = 0;
|
|
160 |
$option = "";
|
|
161 |
|
|
162 |
# Create new summary entry if date matches searchdate
|
|
163 |
if ( $tmpEntry{$count}{"timestamp"} =~ /$SearchDate/ ) {
|
|
164 |
if ( $tmpEntry{$count}{"action"} ne "" && $tmpEntry{$count}{"hostname"} ne "" && $tmpEntry{$count}{"message"} ne "" && $tmpEntry{$count}{"ruleid"} ne "" ) {
|
|
165 |
$messages{$tmpEntry{$count}{"hostname"}}{"numAttacks"}++;
|
|
166 |
$messages{$tmpEntry{$count}{"hostname"}}{"attack"}{$tmpEntry{$count}{"sourceIp"}}{$tmpEntry{$count}{"ruleid"}} = $tmpEntry{$count}{"message"};
|
|
167 |
$messages{$tmpEntry{$count}{"hostname"}}{$tmpEntry{$count}{"sourceIp"}}{$tmpEntry{$count}{"ruleid"}}++;
|
|
168 |
|
|
169 |
$topips{$tmpEntry{$count}{"sourceIp"}}++;
|
|
170 |
$toprules{$tmpEntry{$count}{"ruleid"}}++;
|
|
171 |
}
|
|
172 |
}
|
|
173 |
|
|
174 |
# Increase counter
|
|
175 |
$count++;
|
|
176 |
|
|
177 |
# Reset values
|
|
178 |
$tmpEntry = ();
|
|
179 |
$tmpEntry{$count}{"action"} = "";
|
|
180 |
$tmpEntry{$count}{"hostname"} = "";
|
|
181 |
$tmpEntry{$count}{"message"} = "";
|
|
182 |
$tmpEntry{$count}{"ruleid"} = "";
|
|
183 |
|
|
184 |
if ( $Debug >= 5 ) {
|
|
185 |
print STDERR "---------------------------------------\n";
|
|
186 |
}
|
|
187 |
}
|
|
188 |
}
|
|
189 |
|
|
190 |
# Start summary
|
|
191 |
if (keys %messages) {
|
|
192 |
print "\nATTACKS BLOCKED ON VHOSTS:\n";
|
|
193 |
foreach my $vhost ( sort {$a cmp $b} keys %messages ) {
|
|
194 |
print "\n" . $vhost . " - " . $messages{$vhost}{"numAttacks"} . " time(s)\n";
|
|
195 |
|
|
196 |
foreach my $fromip (sort {$a cmp $b} keys %{$messages{$vhost}{"attack"}}) {
|
|
197 |
foreach my $ruleid (sort {$a cmp $b} keys %{$messages{$vhost}{"attack"}{$fromip}}) {
|
|
198 |
print " [ip: " . sprintf("%-15s", $fromip) . "] ";
|
|
199 |
print "[id: " . $ruleid . " ] [msg: " . $messages{$vhost}{"attack"}{$fromip}{$ruleid} . "] ";
|
|
200 |
print " - " . $messages{$vhost}{$fromip}{$ruleid} . " time(s)\n";
|
|
201 |
}
|
|
202 |
}
|
|
203 |
|
|
204 |
}
|
|
205 |
}
|
|
206 |
|
|
207 |
# Top 10 blocked IPs
|
|
208 |
if (keys %topips) {
|
|
209 |
print "\nTOP 10 BLOCKED IPS:\n";
|
|
210 |
my $cnt = 0;
|
|
211 |
foreach my $ip ( sort {$topips{$b} <=> $topips{$a}} keys %topips ) {
|
|
212 |
print "\n " . sprintf("%2s", ($cnt + 1)) . ". " . $ip . " - " . $topips{$ip} . " time(s)";
|
|
213 |
$cnt++;
|
|
214 |
if($cnt == 10) { last(); }
|
|
215 |
}
|
|
216 |
print "\n";
|
|
217 |
}
|
|
218 |
|
|
219 |
exit(0)
|