How to delay login attempts after too many attempts (PHP)

I am working on a fairly large website created in PHP that could potentially have many users. I am looking for a way to protect the login screen from automatic attempts. I have already included CAPTCHA verification in the registration form, but I want to consolidate the site more.

StackOverflow had the same issues that I know about, and I know that I am able to implement this myself from scratch (keeping login attempts and their time in db), but I don't like this way:

  • Conceptually, I think that this logic refers to the level of the web server / infrastructure, and not to the application level. I do not like this logic and complexity in my application.
  • I am worried about performance, especially at the database level.
  • I am lazy, at best, not wanting to create such a general utility like this from scratch.

Any tutorial is welcome, I think I'm especially looking for some kind of Apache module that can do this. My platform is PHP5 (using CodeIgniter), Apache2, MySQL 5.

+6
php
source share
3 answers

update: do not use sleep () to limit the speed! it makes no sense. I do not have a better solution at hand.


only sleep(1); good start sleep(1); after a failed login attempt, it’s easy to implement, with almost no errors.

1 second for a person is not so much (especially because attempts to enter the system by people are often not interrupted), but 1 sec / brute force attempt ... sloooow! dictionary attacks may be another problem, but they are in the same domain.

if an attacker also starts connecting to work around this, you are dealing with a kind of DOS attack. the problem is resolved (but now you have another problem).

Some things you should consider:

  • If you block sole IP accounts, there may be problems with private networks.
  • If you block soley accounts based on the username, denial of service attacks will again know the known usernames.
  • IP / username based blocking (where the username is attacked) may work better

my suggestion: full blocking is undesirable (DOS), so the best alternative would be: counting login attempts for a specific username from a unique IP address. you can do this with a simple failed_logins: IP/username/failed_attempts table failed_logins: IP/username/failed_attempts

if login failure, wait(failed_attempts); seconds. every xx minutes, run a cron script that will reduce failed_logins:failed_attempts by one.

Sorry, I can’t provide a ready-made solution, but this should be trivial to implement.

OK OK. here's the pseudo code:

 <?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. The last thing I heard was that in Asia there is a whole country NATed (also, they all know kung fu).

+16
source share

A very fictitious untested example, but I think you will find the main idea here).

 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 errors - I wrote this in a few seconds, but the ad was not tested ... The same can be done by IP, nickname, session_id, etc.

+2
source share

Why don't you wait to “harden” and “scale” your application until you have this problem? Most likely, the scenario is that the application will never have “many users”. It sounds like a premature optimization for me, something to avoid.

  • Once you get the bots, abuse, approve the registration. I would really remove the captcha until you start receiving> 1000 registrations per day.
  • Once you get performance issues, improve performance by removing real bottlenecks.
-3
source share

All Articles