What Is the Best Method to Prevent a Brute Force Attack

What is the best method to prevent a brute force attack?

Sessions are unreliable because they rely on cookies, CAPTCHAs are regularly broken [including ReCAPTCHA]. The only reliable method is deceptively simple: ask a question. Don't use a math question because computers are surprisingly adept at solving those for some reason. Great old standbys are things like:

  • What is the fourth word in the sixth paragraph on this page?
  • What is the name of the author of this site? [hint]

This is stupid-easy to implement, and very difficult for a machine to solve.

As for bute-forcing, try adding two fields to your user table, 'first_failed_login' [INTEGER unix timestamp or DATETIME] and 'failed_login_count'. [INTEGER]

<?php
$bad_login_limit = 3;
$lockout_time = 600;

$first_failed_login, failed_login_count; // retrieve from DB

if(
($failed_login_count >= $bad_login_limit)
&&
(time() - $first_failed_login < $lockout_time)
) {
echo "You are currently locked out.";
exit; // or return, or whatever.
} else if( /* login is invalid */ ) {
if( time() - $first_failed_login > $lockout_time ) {
// first unsuccessful login since $lockout_time on the last one expired
$first_failed_login = time(); // commit to DB
$failed_login_count = 1; // commit to db
} else {
$failed_login_count++; // commit to db.
}
exit; // or return, or whatever.
} else {
// user is not currently locked out, and the login is valid.
// do stuff
}

This will make your login system recognize only 3 login attempts per user every 10 minutes.

How can I protect user pages from brute-force attack

and access it using synchronized set and get methods.

How exactly you suppose to get User from such list? Either during every login attempt you have to iterate over whole list to find that User or you always know exact position in the array or may be the list is sorted so you can use binary search but in this case insertion would be inefficient in terms of complexity.
Also the User structure or wherever you want to store latest failed logins, must be synchronized.

Imho one of the simplest solutions in terms of realization could be the following. Note that no additional threads are needed to reset number of attempts after some time period, but ones in a while you have to clear pairs where the most recent failed login time is beyond observable time frame. Cause other way the structure could grow in size.

ConcurrentHashMap<String, List<Long>> loginFails = new ConcurrentHashMap<>();
int ATTEMPTS_TO_FREEZE = 5;
int TIME_FRAME_IN_MINUTES = 5;

with login as key, and list of couple last failed logins as value. Let the threshold be 5 in our case.
Before login check permission. If 5 fails in last 5 minutes -> reject

List<Long> attempts = loginFails.get(login);
if (attempts != null) {
synchronized(attempts) {
if (attempts.size() == ATTEMPTS_TO_FREEZE
&& attempts.peek() > System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(TIME_FRAME_IN_MINUTES)) {
//return some warning to user, that he exceeded number of attempts
}
}
}

After failed login

Queue<Long> attempts = loginFails.get(login);
if (attempts == null) {
attempts = loginFails.putIfAbsent(login, new LinkedList<Long>());
if (attempts == null) {
attempts = loginFails.get(login);
}
}
synchronized (attempts) {
attempts.add(System.currentTimeMillis());
if (attempts.size() > ATTEMPTS_TO_FREEZE) {
attempts.remove();
}
}

On reset (after clicking on emailed link) you can simply remove entry with such login. Instead of String key you can also store id or whatever (but make sure the key class has equals hashcode contract and is immutable)

Also note that this scheme wouldn't be very efficient if someone tries to crack lots of logins.
And there might be some mistakes in code, but I hope you took the point.

how to log failed login attempts (bruteforce attack prevention)

First, a few considerations, followed by some suggestions at the end.

Remember, brute force can generally be successful, but its a matter of time. So, its a matter of you making that amount of time unattainable as much as possible.

Therefore, it starts way before you are dealing with the brute-force attach such as forcing users to implement higher standard passwords (e.g. phrases and 12+ character passwords, etc...)

Then, there isn't always a one-size fits all solution, so the first order of business is to really define who your intended audience is or will be.

  1. I will say that usually a lockout measure can sound great but have extreme negative affects such as allowing attackers to force a denial of services to your users by inevitably locking legit users out of their accounts.

OWASP lists a number reasons not to implement a lockout solution:

  • An attacker can cause a denial of service (DoS) by locking out large numbers of accounts.
  • Because you cannot lock out an account that does not exist, only
    valid account
  • names will lock. An attacker could use this fact to harvest usernames
    from the site, depending on the error responses.
  • An attacker can cause a diversion by locking out many accounts and
    flooding the help desk with support calls.
  • An attacker can continuously lock out the same account, even seconds
    after an administrator unlocks it, effectively disabling the account.
  • Account lockout is ineffective against slow attacks that try only a
    few passwords every hour.
  • Account lockout is ineffective against attacks that try one password
    against a large list of usernames.
  • Account lockout is ineffective if the attacker is using a
    username/password combo list and guesses correctly on the first
    couple of attempts.
  • Powerful accounts such as administrator accounts often bypass lockout
    policy, but these are the most desirable accounts to attack. Some
    systems lock out administrator accounts only on network-based logins.
  • Even once you lock out an account, the attack may continue, consuming
    valuable human and computer resources.

However, I think you have some reasonable ideas that can be expounded upon such as:

  1. Using Google's reCaptcha (like you suggested).
  2. Imposing a delaying mechanism on each unsuccessful attempt (or early on e.g. 2nd, 3rd attempt..)
  3. Consider some identification mechanism to impose the reCaptcha such as browser fingerprinting or IP address for non-thin clients.
  4. Despite the fact that they use a different username/password, you can still track unsuccessful attempts, and at some number of failed attempts (1, 2, 3...whatever) impose a reCaptcha and delay. So if they retry a same username before a successful login has occurred, they will encounter those restrictions.
  5. A possible BFD (Brute Force Detection) system that can help identify when one is actually occurring.

If you were to use IP addresses as identification, legit users of the same network (external IP address) to be subjugated to a reCapchta and/or delay would only be affected if it was their username that was tried unsuccessful. But if you aren't locking out accounts, then the most they are going to entail is a recaptcha and/or short delay.

But at the end of the day, a brute-force attack that is re-routing IP address and changing username/password on each attempt is not any different necessarily than a high traffic site with legitimate users. It would just appear (possibly) as having a higher number of failed attempts in retrospect.

How do I prevent DoS and BruteForce attacks directed to a REST service

External software/hardware. Why ? The reason is simple you want to protect your service from to much unnecessary workload, and when the checks are done by your service you are not protecting it, you're just making it worse. So DDoS attacks should be stopped before they reach your service, because when they do they eat up resources.

Of course you can employ multilevel security whereas besides firewall you do some checks by your service, but it should be additional solution not primary. Firewall sw/hw is designed to handle and block to much load, your REST service is not.



Related Topics



Leave a reply



Submit