Hi there,
For RT2-0-15, there is no protection from brute force attacks on either
the user/pass combination or on the cookie-strings.
Here is a solution:
Exchange the webrt/autohandler script by the lines below to limit the
number of rejected logins to 10 per minute.
(And be sure, you have installed Cookie::Cookie from cpan)
I would appreciate comments.
Kind Regards
Andreas
Andreas Warnke
3SOFT GmbH, Frauenweiherst. 14, 91058 Erlangen
Tel.: +49-9131-7701-274 mailto:Andreas.Warnke@3SOFT.de
Fax: +49-9131-7701-333 http://www.3SOFT.de
%# $Header: /pro/CVS/rt/rt-2-0-15/webrt-rtee/autohandler,v 1.1
2002/11/07 10:59:31 anwa2219 Exp $
<& /Elements/Footer, %ARGS &>
<%INIT>
my $current_time = time;
$m->{‘rt_base_time’} = $current_time;
----------------------------------------
added by Andreas Warnke
‘Period’ denotes the end of the current observation interval
‘Attacks’ is the number of rejected login tries
during the current observation interval
----------------------------------------
my $ACache = $m->cache;
my $period = $ACache->get(‘Period’) || 0;
my $attacks = $ACache->get(‘Attacks’);
----------------------------------------
----------------------------------------
added by Andreas Warnke
Next observation interval?
(And initialization)
----------------------------------------
if ( $period < $current_time ) {
$period = $current_time + 60;
$attacks = 0;
$ACache->set(‘Period’,$period);
$ACache->set(‘Attacks’,$attacks);
}
----------------------------------------
----------------------------------------
added by Andreas Warnke
AttackEncountered?
----------------------------------------
sub AttackEncountered {
my $ACache = $m->cache;
my $attacks = $ACache->get(‘Attacks’);
$attacks += 1;
$ACache->set(‘Attacks’,$attacks);
}
----------------------------------------
#if it’s a noauth file, don’t ask for auth.
if ($m->base_comp->path =~ ‘^/+NoAuth/’) {
$m->call_next();
$m->abort();
}
----------------------------------------
added by Andreas Warnke
The complete database is locked
if there have been more than 10 attacks.
Q: Why not just disable the login-sequence
A: There are 2 types of brute force attacks:
1) Brute force on the user/pass combination
2) Brute force on a valid session cookie
So: Neither may be served if the system
is under attack
----------------------------------------
elsif ( $attacks > 10 ) {
$m->comp(‘/Elements/Login’, Error => ‘Sorry. RT2 is locked for
60 seconds.’, %ARGS);
$m->abort();
}
----------------------------------------
----------------------------------------
deleted by Andreas Warnke
----------------------------------------
If RT is configured for external auth, let’s get REMOTE_USER
We intentionally don’t test for REMOTE_USER to meet our policy
#elsif ($RT::WebExternalAuth){
$user = $ENV{‘REMOTE_USER’};
$session{‘CurrentUser’} = RT::CurrentUser->new();
$session{‘CurrentUser’}->Load($user);
unless ($session{‘CurrentUser’}->id() ) {
delete $session{‘CurrentUser’};
$m->comp(‘/Elements/Login’, %ARGS, Error=> 'You are not an
authorized user’);
$m->abort();
}
#}
----------------------------------------
If the user is loging in, let’s authenticate
elsif (defined ($user) && defined ($pass)){
$session{'CurrentUser'} = RT::CurrentUser->new();
$session{'CurrentUser'}->Load($user);
unless ($session{'CurrentUser'}->id() ) {
delete $session{'CurrentUser'};
AttackEncountered();
$m->comp('/Elements/Login', %ARGS, Error=> 'Your username or
password is incorrect’);
$m->abort();
};
unless ($session{‘CurrentUser’}->IsPassword($pass)) {
delete $session{‘CurrentUser’};
AttackEncountered();
$m->comp('/Elements/Login', Error => 'Your username or password
is incorrect’, %ARGS);
$m->abort();
}
}
#If we’ve got credentials, lets serve the file up.
if ( (defined $session{‘CurrentUser’}) and
( $session{‘CurrentUser’}->Id) ) {
# If the user isn\'t privileged, they can only see SelfService
if ((! $session{'CurrentUser'}->Privileged) and
($m->base_comp->path !~ '^/+SelfService/') ) {
$m->comp('/SelfService/index.html');
$m->abort();
}
else {
$m->call_next;
}
}
#If we have no credentials
else {
AttackEncountered();
$m->comp(‘/Elements/Login’, %ARGS);
$m->abort();
}
</%INIT>
<%ARGS>
$user => undef
$pass => undef
</%ARGS>