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:
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…
SuperWebDeveloper.com is Digg proof thanks to caching by WP Super Cache!