开发者

Timed session variables in PHP? I am trying to lock people out for failed logins

I am having trouble searching for what I am looking for. I figure it is best I ask here, so I can also find out what is the best practice or method for what I am attempting.

I want to make a lockout script that prevents people from trying to login in too many times to prevent password cracking. I ha开发者_JS百科ve one that makes a fade-in pop-up, which creates a slight delay, but to prevent spamming and JavaScript being turned off, I want a more persistent way of preventing someone from trying to login in too many times. I thought session variables would be best for this, but I have no idea how to "time" it.

Can anyone help? I'm using PHP and JavaScript (with jQuery).


First of all, don't lock an account, if someone hits the cap prompt them with reCaptcha.

You cannot use the $_SESSION variable for this because this is bound to a cookie value. If someone is brute forcing the username/password then they can just get a new cookie, and a new $_SESSION. You MUST use a database for this. for every failed login you should make a entry in a simple database with at least two columns ip, timestamp. You should have timestamp set to the current time on insert. When someone logs in you should look

select count(ip) from brute_force_protection where DATE_SUB(NOW(),INTERVAL 1 DAY)>=timestamp and ip='".$_SERVER['remote_addr']."'

Count up the number of cases, if its more than 3, then ban that ip. You could do an mysql_real_escape_string() around the remote_addr, but in all reality this value is pulled directly from apache's TCP socket and the attacker cannot control this value unless he can poison your variable name space (which could be done with extract()).

EDIT:
You could combine this approach with premiso's and lock ip addresses and accounts to produce a very solid system. Where in you can protect against attackers with a list of proxy servers or a botnet, and you can protect against someone trying the same password for all user accounts.


Session variables have a flaw in that they just have to deny cookies and then they are exempt.

You would be better off creating a table for this in a database with the userid.

create table failedlogins (
    id INT NOT NULL auto_increment,
    user_id INT NOT NULL,
    time_tried DATETIME NOT NULL,
    primary key(id),
    index(user_id));

Then you just insert a record on a failed attempt. Then, when the user attempts to login you check "loginLocked($user);" which would query that table for the current time - x minutes (where x minutes is the time you want spaced through x attempts) So say 3 attempts allowed per 5 minutes:

function loginLocked($user) {
    $query = "SELECT count(fl.id) FROM failedlogins fl 
                 JOIN user u ON fl.user_id = u.id
                 WHERE time_tried < DATE_SUB(NOW(), INTERVAL 5 MINUTE) AND u.username = '" . mysql_real_escape_string($user) . "'";

    $res = mysql_query($query) or trigger_error("Failed Login Query failed: " . mysql_error();

    $attempts = mysql_result($res, 0, 0);

    return ($res < 3);
}

That assumes the tables etc. But should give you a good start / idea on how to handle it. You will have to insert an entry each time a login fails.

EDIT:

My SQL Time check may be wrong, as I do not have this setup and I wrote it on the spot, that might be an area that needs adjusting.

Added the user to the where clause, sorry forgot about that.

Clarification: Yea, Locked should be more or less a (re)Captcha is now required to access the account on it's next login attempt.


Depends on what you want to achieve you can use either session variables (as Rich Adams proposes) or save login attempts in database (if you want, for example, temporary block an account after entering an incorrect password few times)


First of all using session to prevent people from brute-forcing password is a bad idea. Session rely on cookie and if you just omit to send cookie each time you make an attempt the server will create a new session each time and you won't be able to stop anything no mater the script you are using.

What you could do is the following, in your database containing the users data, add a field named lastAttempt containing the time at witch the last attempt was made for that user. If the delay between the last attempt is too short you display an error if the delay was ok, just update it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜