Protect weak passwords with login trap
If one thing is for sure, the weaker the user, the weaker the password they use. Its a disaster waiting to happen. I decided to shore things up on a site I take care of just so I can sleep at night. It has lots of users, but weak ones. Many sites out there already have safeguards in place to forbid further login attempts if you keep failing. If you let users own their passwords, and you probably do, there are no doubt some weak ones that could fall to some kind of rainbow attack if you allow an attacker to keep trying. There should be more than one example of this process on the web to compare this to.
It would work like this:
- set a number of allowed login attempts.
- set the time limit in seconds for duration of access denial.
- keep track of the number of failed login attempts.
- keep track of when login attempts started with timestamp function.
- test for meeting or exceeding the number of allowed login attempts.
- let them keep trying if they have waited past the time limit.
- set a time limit for when they can come back, and forbid them.
- give them some messages and links to help.
- if the login has been successful, wipe out all the tracking for login attempts.
- You are done.
Here we go, into your login processor after initial validation and constructing a sql query.
$loginAttemptsAllowed = 5;
if( $_SESSION['loginAttempt']['Count'] <= $loginAttemptsAllowed ) {
$result = $db->queryRow($sql); // only query db if allowed to do so
}
if( !$result ){
$seconds = 300; // 5 minutes
// if trying again after lockout time limit ....
if( $_SESSION['loginAttempt']['Count'] >= $loginAttemptsAllowed ) {
$difference = abs($_SESSION['loginAttempt']['LockoutTime'] - $_SESSION['loginAttempt']['Time']);
$diffSeconds = round($difference);
if( $diffSeconds > $seconds ) {
unset($_SESSION['loginAttempt']); // they failed but have a new set of chances
} else {
$minutes = $seconds / 60;
$message = "Sorry, you have had $loginAttemptsAllowed failed login attempts. <br />
We temporarily forbid access in order to protect your private information. <br />
Please wait $minutes minutes before logging on again.";
}
} else {
if( !isset($_SESSION['loginAttempt']['Time']) ) {
$_SESSION['loginAttempt']['Time'] = get_microtime();
$_SESSION['loginAttempt']['Count'] = 1;
} else {
$_SESSION['loginAttempt']['Count']++;
}
if( $_SESSION['loginAttempt']['Count'] >= $loginAttemptsAllowed ) {
$_SESSION['loginAttempt']['LockoutTime'] = get_microtime();
}
$message = "login error";
}
addMessage($message, "MsgErr");
redirect($_SESSION["backPage"]);
exit();
}
….. go on and log them. Dont forget to unset( $_SESSION['loginAttempt'] );
// a couple of the functions in there are custom ones, they are basically just wrappers.
// I forget where I got the following function, but it is used for benchmarking. Maybe php.net?
function get_microtime() {
$mtime = microtime();
$mtime = explode(" ",$mtime);
$mtime = doubleval($mtime[1]) + doubleval($mtime[0]);
return ($mtime);
}
So there you have it. Forcing users to have highly secure passwords, while a good idea, is not always possible.
Keep your users safe. And curses to wordpress for screwing up my code formatting…