Misc:Abuse Log: Difference between revisions
From Amar
Jump to navigationJump to search
comment6, http://hces1.fas.harvard.edu/gallery/ cheap viagra, lmyvj, |
No edit summary |
||
(17 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
<pre> | |||
#!/usr/bin/perl -w | |||
use strict; | |||
use Data::Dumper; | |||
use DBI; | |||
use Config::IniFiles; | |||
use Net::Telnet; | |||
$| = 1; | |||
our $user = 'admin'; | |||
our $pass = 'xxxxxxxxx'; | |||
my $host1 = '192.168.20.1'; | |||
my $name1 = 'A'; | |||
my $host2 = '192.168.20.3'; | |||
my $name2 = 'B'; | |||
my $badip = ''; | |||
# Requests of interest. Remember to do the regular expression | |||
my $log_events = { '.page' => 1, | |||
'.wmv' => 2, | |||
'.mov' => 2, | |||
'.cgi' => 3, | |||
'.pl' => 3, | |||
'.html' => 4, | |||
}; | |||
my $ids_events = { '.jpg' => 5, | |||
'.bmp' => 5, | |||
'.png' => 5, | |||
'.gif' => 5, | |||
}; | |||
my $log_exts = join("\|",keys(%$log_events)); | |||
$log_exts =~ s/\./\\\./g; | |||
my $log_ext_match = qr/($log_exts)$/; | |||
my $ids_exts = join("\|",keys(%$ids_events)); | |||
$ids_exts =~ s/\./\\\./g; | |||
my $ids_ext_match = qr/($ids_exts)$/; | |||
my $dir_match = qr{/}; | |||
my $max_hits = { 1 => 60, | |||
2 => 12, | |||
3 => 30, | |||
4 => 120, | |||
5 => 20, | |||
}; | |||
my $pattern = qr/([0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+/; | |||
# print Data::Dumper->Dump([$log_exts, $log_ext_match],[qw(log_exts log_ext_match)]); | |||
my $exclude = {}; | |||
&check_ip($exclude); | |||
my $db = 'ABUSE'; | |||
my $cfg = Config::IniFiles->new( -file=> '/etc/db_connect.conf', -default=> 'DEFAULT'); | |||
my $dbi = "DBI:mysql:".$cfg->val($db,"name").":".$cfg->val($db,"host"); | |||
my $dbh = DBI->connect($dbi,$cfg->val($db,'user'),$cfg->val($db,'password'), {RaiseError => 1, AutoCommit => 0}); | |||
my $sth_ins = $dbh->prepare( | |||
qq[INSERT INTO abuse_log | |||
(IP,event_id,bucket_id,hits) | |||
VALUES (?,?,MINUTE(NOW()),1) | |||
]); | |||
my $sth_upd = $dbh->prepare( | |||
qq[UPDATE abuse_log | |||
SET hits = hits + 1 | |||
WHERE IP = ? AND event_id = ? AND bucket_id = MINUTE(NOW()) | |||
]); | |||
my $sth_get = $dbh->prepare( | |||
qq[ SELECT hits FROM abuse_log | |||
WHERE IP = ? AND event_id = ? AND bucket_id = MINUTE(NOW()) | |||
]); | |||
my $sth_log = $dbh->prepare( | |||
qq[ INSERT INTO blocked | |||
(IP,event_id,hits) | |||
VALUES (?,?,?) | |||
]); | |||
open ("STDOUT", ">>$ARGV[0]") || die $!; | |||
while (my $line = <STDIN>) { | |||
chomp $line; | |||
my @fields = split /\|/, $line; | |||
my %fields = map { split /\=/,$_ } @fields; | |||
if ( $fields{U} =~ /$log_ext_match/ ) { | |||
# print STDOUT Data::Dumper->Dump([\%fields],[qw(*fields)]); | |||
my $event = $1; | |||
my $ip = $fields{I}; | |||
my $subnet = undef; | |||
if ($ip =~ $pattern) { | |||
$subnet = $1; | |||
}; | |||
if (exists($exclude->{$ip}) || exists($exclude->{$subnet})) { | |||
print STDOUT $line."\n"; | |||
next; | |||
} | |||
my $event_id = $log_events->{$event}; | |||
my $max = $max_hits->{$event_id}; | |||
# Assume UPDATE and catch error | |||
eval{ | |||
$sth_get->execute($ip,$event_id); | |||
}; | |||
unless ($@) { | |||
my ($hits) = $sth_get->fetchrow_array(); | |||
$hits ||= 0; | |||
# print STDOUT Data::Dumper->Dump([$ip,$event,$event_id,$max,$hits],[qw(ip event event_id max hits)]); | |||
if ($hits > $max) { | |||
print STDOUT "***** ABUSE **** $ip $event ( $hits )\n"; | |||
&disable_ip($ip); | |||
eval { | |||
open ABUSE_LOG, ">>/nfsroot/logs/log_abuse.log" or print STDOUT $!; | |||
print ABUSE_LOG "***** ABUSE **** $ip $event ( $hits )\n"; | |||
print ABUSE_LOG Data::Dumper->Dump([\%fields, $hits, $max],[qw(*fields hits max)]); | |||
close ABUSE_LOG; | |||
}; | |||
eval { | |||
$sth_log->execute($ip,$event_id,$hits); | |||
}; | |||
} | |||
my $rv; | |||
eval{ | |||
# print STDOUT "Updating"; | |||
$rv = $sth_upd->execute($ip,$event_id); | |||
# print STDOUT "Error : '$@".$dbh->errstr."' rv = '$rv'\n"; | |||
}; | |||
if ($@ || $rv == 0) { | |||
eval{ | |||
# print STDOUT "Inserting "; | |||
$sth_ins->execute($ip,$event_id); | |||
}; | |||
} | |||
if ($@) { | |||
print STDOUT "BAD db: $@\n"; | |||
$dbh->rollback(); | |||
} else { | |||
$dbh->commit(); | |||
} | |||
} | |||
print STDOUT $line."\n"; | |||
} elsif ( $fields{U} =~ /$ids_ext_match/ ) { | |||
my $event = $1; | |||
my $ip = $fields{I}; | |||
my $subnet = undef; | |||
if ($ip =~ $pattern) { | |||
$subnet = $1; | |||
}; | |||
if (exists($exclude->{$ip}) || exists($exclude->{$subnet})) { | |||
print STDOUT $line."\n"; | |||
next; | |||
} | |||
my $event_id = $ids_events->{$event}; | |||
my $max = $max_hits->{$event_id}; | |||
# IDS case #1 | |||
# /home/www/v3/images/images/images/images/images/images/images/images/images/images .... | |||
# count the no of / and if above a #, kill the IP | |||
my @dirs = split($dir_match, $fields{U}); | |||
my $hits = scalar(@dirs); | |||
# Log it | |||
if ($hits>$max) { | |||
print STDOUT "***** ABUSE **** $ip $event ( $hits )\n"; | |||
&disable_ip( $ip); | |||
eval { | |||
open ABUSE_LOG, ">>/nfsroot/logs/log_abuse.log" or print STDOUT $!; | |||
print ABUSE_LOG "***** ABUSE **** $ip $event ( $hits )\n"; | |||
print ABUSE_LOG Data::Dumper->Dump([\%fields, $hits, $max],[qw(*fields hits max)]); | |||
close ABUSE_LOG; | |||
}; | |||
eval { | |||
$sth_log->execute($ip,$event_id,$hits); | |||
}; | |||
} | |||
} | |||
# Temp LOG ALL - bad bad bad | |||
# print STDOUT $line."\n"; | |||
} | |||
close (STDOUT); | |||
$sth_log->finish; | |||
$sth_ins->finish; | |||
$sth_upd->finish; | |||
$sth_get->finish; | |||
$dbh->disconnect; | |||
exit 0; | |||
sub hold_it { | |||
my ($host,$name, @IPs) = @_; | |||
my $session = Net::Telnet->new (Timeout => 10, Prompt => '/.*#.*$/', Dump_log => '/tmp/telnet.log'); | |||
# print "$host: @IPs\n"; | |||
$session->open($host); | |||
$session->put($user."\n"); | |||
$session->waitfor ('/.*Password:.*/'); | |||
$session->put($pass."\n"); | |||
# $session->login($user, $pass); | |||
#print $session->cmd(String => 'admin'); | |||
# $session->waitfor('/ Name/'); | |||
#$session->waitfor('/Password.*/'); | |||
#print $session->cmd('g0dm0d3'); | |||
$session->waitfor('/.*'.$name.'#.*/'); | |||
my @output = $session->cmd('config t'."\n"); | |||
my $res = join("\n",@output); | |||
$res .= "\n"; | |||
# $session->waitfor('/.*A\(config\)#.*/'); | |||
# Execute a command | |||
# my @output = $session->cmd('show server real l83'."\n"); | |||
# $session->waitfor('/.*\(config\)#.*/'); | |||
foreach my $badip (@IPs) { | |||
$res .= "$badip \n"; | |||
@output = $session->cmd("security hold-source-ip $badip 60\n"); | |||
$res .= join("\n",@output); | |||
$res .= "\n"; | |||
} | |||
@output = $session->cmd('end'); | |||
$res .= join("\n",@output); | |||
$res .= "\n"; | |||
if (0) { | |||
@output = $session->cmd('exit'); | |||
$res .= join("\n",@output); | |||
$res .= "\n"; | |||
# $res .= $session->cmd('exit'); | |||
} | |||
$session->close; | |||
print STDOUT $res; | |||
}; | |||
sub disable_ip { | |||
my (@ips) = @_; | |||
&hold_it($host1,$name1,@ips); | |||
&hold_it($host2,$name2,@ips); | |||
} | |||
sub check_ip { | |||
my ($exclude) = @_; | |||
my $ips = [qw( | |||
195.92.67.71 | |||
166.102.104.65 | |||
24.191.101.131 | |||
211.50.250.249 | |||
152.163.207.214 | |||
213.154.134.157 | |||
68.47.133.228 | |||
63.118.66.11 | |||
166.102.104.65 | |||
206.154.135.67 | |||
208.236.105 | |||
209.217.134.7 | |||
12.8.9.140 | |||
157.130.79.70 | |||
209.217.134.10 | |||
65.116.11.120 | |||
65.116.11.115 | |||
4.36.232 | |||
4.36.233 | |||
4.36.234 | |||
66.28.24 | |||
208.62.228 | |||
208.62.229 | |||
208.62.230 | |||
66.194.164.160 | |||
66.194.164.162 | |||
66.194.164.157 | |||
66.194.164.200 | |||
69.25.84.2 | |||
66.165.178 | |||
65.223.64 | |||
64.38.240 | |||
64.38.241 | |||
66.37.115 | |||
64.74.164 | |||
38.118.131 | |||
)]; | |||
%$exclude = map {$_ => 1 } @$ips; | |||
} | |||
</pre> |
Latest revision as of 03:07, 8 November 2011
#!/usr/bin/perl -w use strict; use Data::Dumper; use DBI; use Config::IniFiles; use Net::Telnet; $| = 1; our $user = 'admin'; our $pass = 'xxxxxxxxx'; my $host1 = '192.168.20.1'; my $name1 = 'A'; my $host2 = '192.168.20.3'; my $name2 = 'B'; my $badip = ''; # Requests of interest. Remember to do the regular expression my $log_events = { '.page' => 1, '.wmv' => 2, '.mov' => 2, '.cgi' => 3, '.pl' => 3, '.html' => 4, }; my $ids_events = { '.jpg' => 5, '.bmp' => 5, '.png' => 5, '.gif' => 5, }; my $log_exts = join("\|",keys(%$log_events)); $log_exts =~ s/\./\\\./g; my $log_ext_match = qr/($log_exts)$/; my $ids_exts = join("\|",keys(%$ids_events)); $ids_exts =~ s/\./\\\./g; my $ids_ext_match = qr/($ids_exts)$/; my $dir_match = qr{/}; my $max_hits = { 1 => 60, 2 => 12, 3 => 30, 4 => 120, 5 => 20, }; my $pattern = qr/([0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+/; # print Data::Dumper->Dump([$log_exts, $log_ext_match],[qw(log_exts log_ext_match)]); my $exclude = {}; &check_ip($exclude); my $db = 'ABUSE'; my $cfg = Config::IniFiles->new( -file=> '/etc/db_connect.conf', -default=> 'DEFAULT'); my $dbi = "DBI:mysql:".$cfg->val($db,"name").":".$cfg->val($db,"host"); my $dbh = DBI->connect($dbi,$cfg->val($db,'user'),$cfg->val($db,'password'), {RaiseError => 1, AutoCommit => 0}); my $sth_ins = $dbh->prepare( qq[INSERT INTO abuse_log (IP,event_id,bucket_id,hits) VALUES (?,?,MINUTE(NOW()),1) ]); my $sth_upd = $dbh->prepare( qq[UPDATE abuse_log SET hits = hits + 1 WHERE IP = ? AND event_id = ? AND bucket_id = MINUTE(NOW()) ]); my $sth_get = $dbh->prepare( qq[ SELECT hits FROM abuse_log WHERE IP = ? AND event_id = ? AND bucket_id = MINUTE(NOW()) ]); my $sth_log = $dbh->prepare( qq[ INSERT INTO blocked (IP,event_id,hits) VALUES (?,?,?) ]); open ("STDOUT", ">>$ARGV[0]") || die $!; while (my $line = <STDIN>) { chomp $line; my @fields = split /\|/, $line; my %fields = map { split /\=/,$_ } @fields; if ( $fields{U} =~ /$log_ext_match/ ) { # print STDOUT Data::Dumper->Dump([\%fields],[qw(*fields)]); my $event = $1; my $ip = $fields{I}; my $subnet = undef; if ($ip =~ $pattern) { $subnet = $1; }; if (exists($exclude->{$ip}) || exists($exclude->{$subnet})) { print STDOUT $line."\n"; next; } my $event_id = $log_events->{$event}; my $max = $max_hits->{$event_id}; # Assume UPDATE and catch error eval{ $sth_get->execute($ip,$event_id); }; unless ($@) { my ($hits) = $sth_get->fetchrow_array(); $hits ||= 0; # print STDOUT Data::Dumper->Dump([$ip,$event,$event_id,$max,$hits],[qw(ip event event_id max hits)]); if ($hits > $max) { print STDOUT "***** ABUSE **** $ip $event ( $hits )\n"; &disable_ip($ip); eval { open ABUSE_LOG, ">>/nfsroot/logs/log_abuse.log" or print STDOUT $!; print ABUSE_LOG "***** ABUSE **** $ip $event ( $hits )\n"; print ABUSE_LOG Data::Dumper->Dump([\%fields, $hits, $max],[qw(*fields hits max)]); close ABUSE_LOG; }; eval { $sth_log->execute($ip,$event_id,$hits); }; } my $rv; eval{ # print STDOUT "Updating"; $rv = $sth_upd->execute($ip,$event_id); # print STDOUT "Error : '$@".$dbh->errstr."' rv = '$rv'\n"; }; if ($@ || $rv == 0) { eval{ # print STDOUT "Inserting "; $sth_ins->execute($ip,$event_id); }; } if ($@) { print STDOUT "BAD db: $@\n"; $dbh->rollback(); } else { $dbh->commit(); } } print STDOUT $line."\n"; } elsif ( $fields{U} =~ /$ids_ext_match/ ) { my $event = $1; my $ip = $fields{I}; my $subnet = undef; if ($ip =~ $pattern) { $subnet = $1; }; if (exists($exclude->{$ip}) || exists($exclude->{$subnet})) { print STDOUT $line."\n"; next; } my $event_id = $ids_events->{$event}; my $max = $max_hits->{$event_id}; # IDS case #1 # /home/www/v3/images/images/images/images/images/images/images/images/images/images .... # count the no of / and if above a #, kill the IP my @dirs = split($dir_match, $fields{U}); my $hits = scalar(@dirs); # Log it if ($hits>$max) { print STDOUT "***** ABUSE **** $ip $event ( $hits )\n"; &disable_ip( $ip); eval { open ABUSE_LOG, ">>/nfsroot/logs/log_abuse.log" or print STDOUT $!; print ABUSE_LOG "***** ABUSE **** $ip $event ( $hits )\n"; print ABUSE_LOG Data::Dumper->Dump([\%fields, $hits, $max],[qw(*fields hits max)]); close ABUSE_LOG; }; eval { $sth_log->execute($ip,$event_id,$hits); }; } } # Temp LOG ALL - bad bad bad # print STDOUT $line."\n"; } close (STDOUT); $sth_log->finish; $sth_ins->finish; $sth_upd->finish; $sth_get->finish; $dbh->disconnect; exit 0; sub hold_it { my ($host,$name, @IPs) = @_; my $session = Net::Telnet->new (Timeout => 10, Prompt => '/.*#.*$/', Dump_log => '/tmp/telnet.log'); # print "$host: @IPs\n"; $session->open($host); $session->put($user."\n"); $session->waitfor ('/.*Password:.*/'); $session->put($pass."\n"); # $session->login($user, $pass); #print $session->cmd(String => 'admin'); # $session->waitfor('/ Name/'); #$session->waitfor('/Password.*/'); #print $session->cmd('g0dm0d3'); $session->waitfor('/.*'.$name.'#.*/'); my @output = $session->cmd('config t'."\n"); my $res = join("\n",@output); $res .= "\n"; # $session->waitfor('/.*A\(config\)#.*/'); # Execute a command # my @output = $session->cmd('show server real l83'."\n"); # $session->waitfor('/.*\(config\)#.*/'); foreach my $badip (@IPs) { $res .= "$badip \n"; @output = $session->cmd("security hold-source-ip $badip 60\n"); $res .= join("\n",@output); $res .= "\n"; } @output = $session->cmd('end'); $res .= join("\n",@output); $res .= "\n"; if (0) { @output = $session->cmd('exit'); $res .= join("\n",@output); $res .= "\n"; # $res .= $session->cmd('exit'); } $session->close; print STDOUT $res; }; sub disable_ip { my (@ips) = @_; &hold_it($host1,$name1,@ips); &hold_it($host2,$name2,@ips); } sub check_ip { my ($exclude) = @_; my $ips = [qw( 195.92.67.71 166.102.104.65 24.191.101.131 211.50.250.249 152.163.207.214 213.154.134.157 68.47.133.228 63.118.66.11 166.102.104.65 206.154.135.67 208.236.105 209.217.134.7 12.8.9.140 157.130.79.70 209.217.134.10 65.116.11.120 65.116.11.115 4.36.232 4.36.233 4.36.234 66.28.24 208.62.228 208.62.229 208.62.230 66.194.164.160 66.194.164.162 66.194.164.157 66.194.164.200 69.25.84.2 66.165.178 65.223.64 64.38.240 64.38.241 66.37.115 64.74.164 38.118.131 )]; %$exclude = map {$_ => 1 } @$ips; }