Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Limiting the number of failed login attemps

I want to limit the failed login attempts. For example, if a specific user attempt to login with wrong username or password 4 times, i should show the CAPTCHA 4th time instead of blocking for some specific time, and keep showing CAPTCHA unless he supplies valid username and password. Once the user has successfully logged in, the login attempt is reset to ZERO.

Is the idea of checking the username instead of IP address OK in security point of view? Can this approach be implemented without using database?, as I think I don't need to store time because i will just show recaptcha? Please give your opinion.

like image 510
Roman Avatar asked Jun 15 '11 12:06

Roman


3 Answers

You don't want to use the database for the 'number of failed logins'-check? Then just use a cookie and check it. Sure, they can remove it, but it's a hassle.

However, I suspect that you already are getting the username and password from the database, why not also fetch the last number of failed logins while you are at it?

if (isset($_POST['submit_login'])) {

    if (isset($_POST['username']) && isset($_POST['password'])) {
        $username = mysql_real_escape_string($_POST['username']);
        $password = mysql_real_escape_string($_POST['password']);
        // id = unique primary key
        $rs = mysql_query('SELECT id,Username,Password,Failed_logins,IP_address FROM Users WHERE Username = '.$username.'');
        $num = mysql_num_rows($rs);
        if ($num > 0) {
            // I would add a password hash here to $password, and check against the hashed Password from the database
            // But let's check the clean passwords
            $row = mysql_fetch_array($rs);
            if ($password == $row['Password']) {
                // Successful login, set session or whatever you need
                // Reset failed logins
                mysql_query('UPDATE Users SET Failed_logins = 0 WHERE id = '.$row['id'].'');
                header('location: success.php');
            } else {
                // Failed password check
                if ($row['Failed_logins'] > 3) {
                    // Redirect to captcha
                    header('location: captcha.php');
                } else {
                    $ip = $_SERVER['REMOTE_ADDR'];
                    if ($row['IP_address'] != $ip) {
                        // New ip adress, reset failed logins
                        $failed_logins = 0;
                    } else {
                        // Increment failed logins
                        $failed_logins = $row['Failed_logins']+1;
                    }
                    mysql_query('UPDATE Users SET Failed_logins = '.$failed_logins.',IP_address = '.$ip.' WHERE id = '.$row['id'].' ');
                } // End check Failed_logins > 3
            }
        } else {
            // No such Username found in database
            $error = 'no_such_username';
        } // End username check from database

    } else {
        // Either username or password is missing
        $error = 'incomplete_form';
    } // end check for username and password

} // end main submit_login check

Something like that.

EDIT:

This is really old code and I see some problems with it now. But, at least you should always use PDO (prepared statements) for inserting data in your database.

like image 143
Mattis Avatar answered Oct 21 '22 20:10

Mattis


What are you protecting?

Random user-only content, username.

Banking information (I doubt..) or other sensitive data, IP might be okay, provided you use ranges.

Are you asking how to do it, or which you should use?

like image 25
Anonymous Avatar answered Oct 21 '22 20:10

Anonymous


You do need time, how would you otherwise determine if an login attempt has expired? If I would fail to login 4 times over a 10 year time span I would get blocked. You want to block those who attempt multiple login attempts in a short time span.

I suggest you use an database - as you will keep an detailed history of logins at the same time. But an memory based solution like memcached could also suffice.

To elaborate on which security to implement: a combination!

Combine the used username and ip address and store them into your database.

  1. Use the login attempts on your username to directly protect your users from attempts.
  2. Use the ip address information to observe an detect only, and take action if needed.
like image 43
Wesley van Opdorp Avatar answered Oct 21 '22 21:10

Wesley van Opdorp