[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Authentication probe is an attempt of a user to use other user's account, by guessing his password. The obvious indication of an authentication probe is appearence of several consecutive authentication failures for the same user. Of course, if the intruder is given sufficient number of such probes he will sooner or later succeed in finding the actual password. The conventional method to prevent this from occurring is to keep failure counters for each user and to lock the account when its failure countrer reaches a predefined limit. Notice that a legitimate user may fail (sometimes even several times in sequence) in entering his password so, two important points should always be observed. First, failure counters record the number of consecutive authentication failures and they are reset after each successive authentication. Secondly, the maximum number of allowed consecutive failures should be set sufficiantly high.
The version 1.3 offers two ways for controlling authentication probes: using external programs and using special SQL queries.
To control authentication probes using external programs, use the
combination of Exec-Program-Wait
and
Auth-Failure-Trigger
. The program specified by
Auth-Failure-Trigger
is executed each time an authentication
attempt failed. When both attributes are used together, the program
invoked by Auth-Failure-Trigger
can update the failure
counter, and the one invoked by Exec-Program-Wait
can compare
the counter value with the predefined limit and reject authentication
when both values become equal. Such approach is most useful in
conjunction with BEGIN
profile.
Let's suppose the program `/sbin/check_failure' accepts a user name and returns 1 if the failure counter for this user has reached maximum allowed value. Otherwise it returns 0 and clears the counter. Another program, `/sbin/count_failure' increases failure counter value for the given user name. Assuming our basic authentication type is `PAM', the `raddb/users' file will look as follows:
BEGIN NULL Exec-Program-Wait = "/sbin/check_failure %C{User-Name}", Auth-Failure-Trigger = "/sbin/count_failure %C{User-Name}", Fall-Through = Yes DEFAULT Auth-Type = PAM Service-Type = Framed-User, Framed-Protocol = PPP [... Other profiles ...] |
The BEGIN
profile will be executed before any other profile.
It will add to the RHS Exec-Program-Wait
and
Auth-Failure-Trigger
attributes and then radiusd
will
proceed to finding a matching profile (due to Fall-Through
attribute). When such profile is found, the user will be authenticated
according to the method set up by the profile's Auth-Type
attribute. If authentication fails, `/sbin/count_failure'
will be called and the user name passed to it as the argument. Otherwise,
`/sbin/check_failure' will be invoked.
To complete the example, here are working versions of both programs.
Failure counters for each user name are kept in separate file in
`/var/log/radius/fails' directory. Both programs are written
in bash
.
#! /bin/bash test $# -eq 1 || exit 1 MAXFAIL=8 REGDIR=/var/log/radius/fails if [ -r "$REGDIR/$1" ]; then read COUNT < "$REGDIR/$1" COUNT=$((COUNT+1)) else COUNT=1 fi echo $COUNT > "$REGDIR/$1" # End of /sbin/count_failure |
#! /bin/bash test $# -eq 1 || exit 1 MAXFAIL=8 REGDIR=/var/log/radius/fails if [ -r "$REGDIR/$1" ]; then read COUNT < "$REGDIR/$1" if [ $COUNT -ge $MAXFAIL ]; then echo "Reply-Message=\"Too many login failures. Your account is locked\"" exit 1 else rm "$REGDIR/$1" fi fi exit 0 # End of check_failure |
Another way of controlling authentication probes is by using
SQL database to store failure counters. Two queries are
provided for this purpose in `raddb/sqlserver' file:
auth_success_query
is executed upon each successful
authentication, and auth_failure_query
is executed upon
each authentication failure. Both queries are not expected to return
any values. One obvious purpose of auth_failure_query
would be to
update failure counters and that of auth_success_query
would be
to clear them. The auth_query
or group_query
should then
be modified to take into account the number of authentication
failures.
The default SQL configuration GNU Radius is shipped with provides a working example of using these queries. Let's consider this example.
First, we create a special table for keeping authentication failure counters for each user:
CREATE TABLE authfail ( # User name this entry refers to user_name varchar(32) binary default '' not null, # Number of successive authentication failures for this user count int, # Timestamp when this entry was last updated time datetime DEFAULT '1970-01-01 00:00:00' NOT NULL, # Create a unique index on user_name UNIQUE uname (user_name) ); |
The query auth_fail_query
will increment the value of
count
column for the user in question:
auth_failure_query UPDATE authfail \ SET count=count+1,time=now() \ WHERE user_name='%C{User-Name}' |
The query auth_success_query
will clear count
:
auth_success_query UPDATE authfail \ SET count=0,time=now() \ WHERE user_name='%C{User-Name}' |
Now, the question is: how to use this counter in authentication? The answer is quite simple. First, let's create a special group for all the users whose authentication failure counter has reached its maximum value. Let this group be called `*LOCKED_ACCOUNT*'. We'll add the following entry to `raddb/users':
DEFAULT Group = "*LOCKED_ACCOUNT*", Auth-Type = Reject Reply-Message = "Your account is currently locked.\n\ Please, contact your system administrator\n" |
which will reject all such users with an appropriate reply message.
The only thing left now is to rewrite group_query
so that it
returns `*LOCKED_ACCOUNT*' when authfail.count
reaches its
maximum value. Let's say this maximum value is 8. Then the following
query will do the job:
group_query SELECT user_group FROM groups \ WHERE user_name='%u' \ UNION \ SELECT CASE WHEN (SELECT count > 8 FROM authfail \ WHERE user_name='%u') THEN '*LOCKED_ACCOUNT*' END |
The default configuration comes with these queries commented out. It is up to you to uncomment them if you wish to use SQL-based control over authentication failures.
Notice the following important points when using this approach:
UNION
. Earlier
versions of MySQL
lacked this support, so if you run
MySQL
make sure you run a reasonably new version (at least
4.0.18).
auth_failure_query
and auth_success_query
assume the database already contains an entry for each user. So,
when adding a new user to the database, make sure to insert
an appropriate record into authfails
table, e.g.
INSERT INTO authfail VALUES('new-user',0,now()); |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |