I'm working on a fairly large web site built in PHP that will potentially have a lot of users. I'm looking into a way to protect the login screen from automated attempts. I have already included a CAPTCHA check on the registration form, yet want to harden the site more.
There have been similar questions on StackOverflow that I know of, and I know I'm capable of implementing this myself from scratch (storing login attempts and their time in the db), yet I dislike that path:
Any advise is appreciated, I think that I'm particularly looking for some kind of Apache module that can do this. My platform is PHP5 (using CodeIgniter), Apache2, MySQL 5.
First, we will create an HTML form with two fields i.e username and password. We will store the IP address in a variable and also create a variable for time. $time=time()-30; // Here you can chnage the attempt lock time. We using 30 here because after 3 failed login attempt, user can't login for 30 second.
Sometimes the hacker might think they know your password, or they might develop a script to guess your password. In that case what you need to do is limit the login attempts. Limiting the failed login attempts will lock a user out if they entered the wrong password more than the specified time.
You need to access your site using your FTP client or file manager, and then go to the /wp-content/plugins/ folder. Once you're there, you can simply delete the limit-login-attempts-reloaded plugin folder. You can now log in to your WordPress admin area.
update: do not use sleep() for rate limiting! this doesn't make sense at all. i don't have a better solution on hand.
a good start would be to just sleep(1);
after a failed login attempt - easy to implement, almost bug-free.
1 second isn't much for a human (especially because login attempts by humans don't fail to often), but 1sec/try brute-force ... sloooow! dictionary attacks may be another problem, but it's in the same domain.
if the attacker starts too may connections to circumvent this, you deal with a kind of DOS-attack. problem solved (but now you've got another problem).
some stuff you should consider:
my suggestion:
complete locking is not desireable (DOS), so a better alternative would be: count the login attempts for a certain username from a unique IP. you could do this with a simple table failed_logins: IP/username/failed_attempts
if the login fails, wait(failed_attempts);
seconds. every xx minutes, run a cron script that decreases failed_logins:failed_attempts
by one.
sorry, i can't provide a premade solution, but this should be trivial to implement.
okay, okay. here's the pseudocode:
<?php
$login_success = tryToLogIn($username, $password);
if (!$login_success) {
// some kind of unique hash
$ipusr = getUserIP() . $username;
DB:update('INSERT INTO failed_logins (ip_usr, failed_attempts) VALUES (:ipusr, 1) ON DUPLICATE KEY UPDATE failed_logins SET failed_attempts = failed_attempts+1 WHERE ip_usr=:ipusr', array((':ipusr' => $ipusr));
$failed_attempts = DB:selectCell('SELECT failed_attempts WHERE ip_usr=:ipusr', array(':ipusr' => $ipusr));
sleep($failed_attempts);
redirect('/login', array('errorMessage' => 'login-fail! ur doin it rong!'));
}
?>
disclaimer: this may not work in certain regions. last thing i heard was that in asia there's a whole country NATed (also, they all know kung-fu).
A very dummy untested example, but I think, you will find here the main idea ).
if ($unlockTime && (time() > $unlockTime))
{
query("UPDATE users SET login_attempts = 0, unlocktime = 0 ... ");
}
else
{
die ('Your account is temporary locked. Reason: too much wrong login attempts.');
}
if (!$logged_in)
{
$loginAttempts++;
$unlocktime = 0;
if ($loginAttempts > MAX_LOGIN_ATTEMPTS)
{
$unlockTime = time() + LOCK_TIMEOUT;
}
query("UPDATE users SET login_attempts = $loginAttempts, unlocktime = $unlocktime ... ");
}
Sorry for the mistakes - I wrote it in some seconds ad didn't test... The same you can do by IP, by nickname, by session_id etc...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With