Apache-BruteWatch
view release on metacpan or search on metacpan
lib/Apache/BruteWatch.pm view on Meta::CPAN
notification will be sent. Time is in seconds.
=head2 BruteNotify
Email address to which notifications will be sent
=head2 BruteForgive
Failed login attempts will be cleaned up after they are this old. Units
are seconds.
=cut
sub handler {
my $r = shift;
# We only care about unauthorized
return OK unless $r->status == 401;
my $user = $r->dir_config('BruteDataUser');
my $pass = $r->dir_config('BruteDataPassword');
my $dbase = $r->dir_config('BruteDatabase');
my $dbh =
DBI->connect( $dbase, $user, $pass,
{ RaiseError => 1, AutoCommit => 1, PrintError => 1 } )
or die $DBI::errstr;
my $time = time;
my $username = $r->user;
my $sth = $dbh->prepare(
"INSERT into bruteattempt (ts ,
username) values (?,?)"
);
$sth->execute( $time, $username );
$sth->finish;
my $count = attacks( $r, $username, $time, $dbh );
my $maxtries = $r->dir_config('BruteMaxTries');
if ( $count > $maxtries ) {
warn(
"Apache::BruteWatch : It appears that $username is under attack. Notification sent."
);
notify( $r, $username, $dbh );
}
return OK;
}
sub attacks {
my ( $r, $username, $time, $dbh ) = @_;
my $count;
my $old = $r->dir_config('BruteMaxTime');
my $sth = $dbh->prepare(
"select count(ID) from bruteattempt where
username = ? and ts > $time - $old"
);
$sth->execute($username);
$sth->bind_columns( \$count );
$sth->fetch;
$sth->finish;
my $forgive = $r->dir_config('BruteForgive');
$sth = $dbh->prepare(
"delete from bruteattempt where
ts > $time - $forgive"
);
$sth->execute;
$sth->finish;
return $count;
}
sub notify {
my ( $r, $username, $dbh ) = @_;
my $count;
warn "Attempting to notify";
# Have they already been notified?
my $sth = $dbh->prepare(
"select count(ID) from brutenotified
where username = ?"
);
$sth->execute($username);
$sth->bind_columns( \$count );
$sth->fetch;
$sth->finish;
return if $count;
my $notify = $r->dir_config('BruteNotify');
my $message = qq~
Apache::BruteWatch
It appears that the username $username is under a brute-force
password attack.
~;
my %mail = (
To => $notify,
From => $notify,
Subject => "User $username under attack",
Message => $message,
);
Mail::Sendmail::sendmail(%mail);
$sth = $dbh->prepare(
"insert into brutenotified
(username, ts )
values
(?,?) "
);
$sth->execute( $username, time );
$sth->finish;
return;
}
=head1 Database
The following is a mysql database table create statement. You'll need to
make the appropriate change to run this on some other database.
CREATE TABLE bruteattempt (
ID int(11) NOT NULL auto_increment,
ts int(11) default NULL,
username varchar(255) default NULL,
PRIMARY KEY (ID)
) TYPE=MyISAM;
CREATE TABLE brutenotified (
ID int(11) NOT NULL auto_increment,
username varchar(255) default NULL,
ts int(11) default NULL,
PRIMARY KEY (ID)
) TYPE=MyISAM;
=head1 AUTHOR
Rich Bowen
rbowen@rcbowen.com
http://www.cre8tivegroup.com
=head1 DATE
( run in 0.531 second using v1.01-cache-2.11-cpan-2398b32b56e )