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.
- 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:
- Using Google's reCaptcha (like you suggested).
- Imposing a delaying mechanism on each unsuccessful attempt (or early on e.g. 2nd, 3rd attempt..)
- Consider some identification mechanism to impose the reCaptcha such as browser fingerprinting or IP address for non-thin clients.
- 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.
- 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
How to Change Default Redirect Url of Laravel 5 Auth Filter
Check If a Remote Page Exists Using PHP
Is This a PHP Date() Bug, or Is There Something Wrong with My Code
Why Are $_Server["Php_Auth_User"] and $_Server["Php_Auth_Pw"] Not Set
How to Set an Absolute Include Path in PHP
PHP Merge Array(S) and Delete Double Values
PHP If Single or Double Equals
How to Minify Js in PHP Easily...Or Something Else
Is There Open-Source Code for Making 'Link Preview' Text and Icons, Like in Facebook
PHP Allocate Color Without Image Resource
How Is MVC Supposed to Work in Codeigniter
Why Does "Echo '2' . Print(2) + 3" Print 521
Decoding Numeric HTML Entities via PHP
How to Keep the Chinese or Other Foreign Language as They Are Instead of Converting Them into Codes
PHP Adds Keys to Decoded and Then Encoded JSON Data
How to Create a Nested-List of Categories in Laravel