0

I don't want by server to get brute forced but I don't want to use a CAPTCHA as they're not user friendly / I don't want to rely on another company - because I'm not going to implement my own captcha system.

I've thought of creating a attempts table with this structure:

________________________________________________________________
|         IP         |      ATTEMPTS      |        LOCK        |
|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|
|       1.1.1.1      |         0          |          2         |
|        ....        |        ....        |        ....        |
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾          Yes I had fun making this

And let the user have 5-10 attempts, before resetting to 0 and increasing the lock time by a factor of 2 - it's in minutes.

Is this a good method to lock out a brute force?

I'd have logic like this on my server: - abstracted

....
* on request to server do below  *

db.query("SELECT * FROM attempts WHERE IP= *REQUEST.IP* ",function(result){
    if (result.rows.length > 0 && result.rows[0].attempts > 5) {
        if (CheckIfExpired(results.rows[0].lock)) {
            if (loginFail) MultplyLockBy2();
            else RemoveFromAttemptsTable();
        } else res.status("403").send("You're locked out");
    } else normalLoginAttempt().ifFal(add1toAttempts());
....

I have a feeling there's a more efficient way to do this natively in SQL, I'm a novice with SQL. (I'm using postgresql).

After looking at this I'm guessing I'd need a start-time field aswell, so I can calculate when the lock has expired.

EDIT: after doing research I've read / am thinking about implementing fail2ban which check's Apache/nginx logs and blocks users; a cookie that allows a user to connect back into their account without Captcha / proof of work, and then make others get captcha; or just a captcha in conjunction with a lockout;

6
  • I really, really hope that that javascript is server side. Moreover, I have absolutely no clue what you're talking about in your last paragraph (the EDIT one), how does a user make other users get a captcha?
    – grochmal
    Commented Oct 9, 2016 at 3:34
  • I recommend you base the lockout on the user name rather than the IP address. Sometimes many users come from a single IP address. And any half-decent attacker will be able to use thousands of IP addresses through open proxies, botnets, etc.
    – paj28
    Commented Oct 9, 2016 at 8:46
  • The javascript is ofcourse in my node server.
    – Tobiq
    Commented Oct 9, 2016 at 17:01
  • @paj28 Then as user will just switch users constantly.
    – Tobiq
    Commented Oct 9, 2016 at 17:03
  • @grochmal ... ptcha how does it know who to catch if the person is changing their IP's consistently, do I apply it accross the account and give the user a special cookie that makes them bypass captcha always on their account? or atleast an extended threshold - this is what I was illuding to when i started talking about a cookie that allows a user to connect back into their account without Captcha / proof of work, and then make others get captcha ...
    – Tobiq
    Commented Oct 9, 2016 at 17:10

2 Answers 2

1

There are some problems I see with your approach.

Firstly, it provides a route to a denial of service attack; someone just needs to keep supplying bad passwords from an ip address to lock it out. Assuming a 1:1 correlation between users and ip addresses is a bit silly.

Secondly, in order to reset an account you need to delete data which is useful in terms of an audit trail. Were you planning on reseting the account after a successful login?

Thirdly, it does not protect against a distributed attack - or one with spoofed addresses.

If it were me, I would go with....

SELECT SUM(score)
FROM (
   SELECT COUNT(*) * ipweight AS score
   FROM logins
   WHERE failed=true
   AND ip=INET_ATON(*client_address*) 
   AND ip <> *trusted_device*
   AND timestamp>NOW - INTERVAL *config_value* MINUTES
   UNION
   SELECT COUNT(*) * acctweight AS score
   FROM logins
   WHERE failed=true
   AND username=*supplied_username* 
   AND ip <> *trusted_device*
   AND timestamp>NOW - INTERVAL *config_value* MINUTES
   UNION
   SELECT COUNT(*) * allweight AS score
   FROM logins
   WHERE failed=true
   AND ip <> *trusted_device*
   AND timestamp>NOW - INTERVAL *config_value* MINUTES
)

(This can be extended with other atrributes such as user agent)

Set a lower threshold than the lockout at which you require the user to complete additional verification (such as a capcha).

Just log the attempt (ip address, username, timestamp, outcome) in the database (not the lockout time).

Note that representing the ip address in its native (integer) format in your database is almost always a good idea. Here it offers the opportunity of aggregating failures across an arbitrary netblock.

8
  • What schema does your query follow, that would probrably help me understand what it's doing.
    – Tobiq
    Commented Oct 9, 2016 at 17:05
  • ip address integer, username string, timestamp datetime, failed boolean
    – symcbean
    Commented Oct 9, 2016 at 17:51
  • When you say integer do you mean just removing the points, or converting into an - 4*8 - 32 bit number
    – Tobiq
    Commented Oct 9, 2016 at 17:54
  • Converting to a 32 bit number (but you should use 128 bits if your db can handle it)
    – symcbean
    Commented Oct 9, 2016 at 17:58
  • arent they 32 bit?
    – Tobiq
    Commented Oct 9, 2016 at 19:48
0

This method isn't very good.

Remember that I don't have to send you requests through your website. I can route my requests through a proxy and send you completely fake IPs. Moreover, the same applies to local storage, cookies (and sessions - which rely on cookies). I can send you requests that have absolutely no identifiying information.

So, this essentially leaves you with two options.

First, lock based on username. This option isn't good, because an anonymous attacker could block you from logging in without it being your fault.

Second, and the good one, is to apply a captcha. I think writing your own captcha is a waste of time and not efficien because today there are very good systems that can interpret written text on captchas and easily solve them. I recommend Google's ReCaptcha - it's proven and tested.

3
  • So never lock out the user, but keep using a captcha?
    – Tobiq
    Commented Oct 9, 2016 at 17:06
  • Then the problem stems down to the captcha how does it know who to catch if the person is changing their IP's consistently, do I apply it accross the account and give the user a special cookie that makes them bypass captcha always on their account? or atleast an extended threshold - this is what I was illuding to when i started talking about a cookie that allows a user to connect back into their account without Captcha / proof of work, and then make others get captcha
    – Tobiq
    Commented Oct 9, 2016 at 17:08
  • You misinterpreted the goal of the captcha. Its purpose isn't to lock out a user, but to counter any bruteforce attempts on passwords (or anything else that might be bruteforced). By verifying a captcha BEFORE verifying input, you essentially force the user to manually enter a captcha every time. And if every request will take him 3-5 seconds, he will be VERY far from breaking any passwords.
    – Tom
    Commented Oct 11, 2016 at 8:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .