It looks like at the moment there is a rate limit of 10 request per minutes for IP address.
I tried with multiple IP addresses, and I didn’t noticed any other rate limit, so with 10 IP addresses I can make 100 requests per minute.
With a decent number of IP addresses available, there are high chances to guess the right 2FA code. Using VPN/VPS services, a similiar attack would be also relatively cheap.
In my opinion it would be very useful to add a per user rate limit, in addition to the per IP one.
If I had more votes I would for sure vote for this, rate limiting on the user level makes more sense than at the IP address level.
I’m starting to wonder if we’re seeing real-world examples of someone doing this? This is the second post on Reddit with someone getting 100’s of emails saying someone logged into their account. They say it’s from multiple IPs.
I would probably implement it in this way;
after too many requests with the wrong OTP (let’s say 20 in an hour):
the user account is flagged as blocked (no further login attempts allowed);
an email is sent to inform the user that someone is trying to guess his OTP;
the email also contains a link with a token that add the user IP in a temporary white list;
finally, the user can log in, he is asked to change his password (as if someone managed to reach the 2FA step, it very likely know the user password), and the account lock is removed.
Further, as a paranoid user, I would also like to receive an email every time a wrong OTP is used, containing also the IP address so I can check if it was me. This kind of email could be sent like only the first time every 24 hour, to prevent email flooding with multiple OTP retries.
This feature is only needed on the 2FA screen. Bitwarden could send an email to the user with a code to let them back in.
Though this would be very similar to the feature request of getting the email after a correct master password is entered and not after successful login. Me personally, I rather have this than blocking by username.
This would be a fantastic feature, it could replace my proposal at the end of my previous message, but in my opinion we would still need some mechanism to prevent an attack from happening, and not just to notify that it is in progress.
Such an attack could be carried out in a few minutes/hours, if it’s done at night while I’m sleeping, by the time I notice it would be too late.
Perhaps I am misunderstanding the scenario here, but if my password is compromised and someone is able to login to my vault, and it is only the OTP that is keeping them out, I don’t care much about rate limiting, I just want the account suspended after 4 or 5 failed attempts.
Ideally, this would also trigger an automatic email to me stating that a suspension has been applied and provide instructions on how to remove the block and advice to change the password.
Is it really the case right now that brute-forcing an OTP does not warn the vault owner or suspend the account after a significant number of failed attempts? To me, that seems like a serious problem.
I don’t think captcha is an optimal solution. It would be a deterrent, but it wouldn’t solve the problem; there are online paid services that solve captchas (with good accuracy because there are humans behind it), so if someone had a high interest in entering an account they could still do it.
In my opinion the only solution is to add attempt limits at the account level or, as I said in one of my posts above and as @dh024 also proposed, suspend/block the account after a low enough number of attempts.
I’m not too worried about a DoS attack, as it would require someone to know the master password in order to occur. And if someone knew my master password, I’d rather be temporarily locked out of the account too, than have someone gain access to it abusively.
That’s fine. Those services take anywhere from 10 to 30 seconds for the human to solve it and with TOTP codes changing every 30 seconds, I don’t see that as an issue.
The problem with locking the account is that it needs to be unlocked. You don’t want to lock out the correct user and you also don’t want the lock-out feature to be abused by an attacker too.
Captchas are not meant to be the solution, the solution is changing your master password. Captchas slow the attacker down greatly, almost to a non-existent problem. We need this slow down so you can warn the user who can then solve the problem by changing their master password.
To be clear, the Captcha would not trigger until 5 failed guesses of the OTP. After 5 failed attempts, you need to solve a Captcha to be able to guess the 6th time. Then Captchas for all next guess from that IP address.
To me, Captchas solve the difficult balance of not locking the user out, warning the user and stopping lockout from being abused by an attacker.
It doesn’t really matter how much time passes before the captcha is solved, the important thing is how many are solved in the same 30 second range, in order to have a better chance of guessing the code. It makes no difference whether the current code or the next one is guessed.
With IP based captcha limit we’ll still have almost the same issue. If someone manage to have a huge amount of IP addresses, he actually don’t care about IP limitation.
Account based captcha limit could mitigate the issue, but personally I would feel safer if the account is blocked after 5-10 attempts.
Locking an account after failed attempts has many problems. If you lock the account you’ll need a way to unlock it.
The first option is to contact support. This creates more work for support and how would support know the legit user is contacting them?
The second option is to use email. You can send a link to the user that allows them to unlock their account. The problem is what if the user doesn’t have access to their email account because the password to it is in the password manager that they can not get into now. Or simply the user doesn’t have access at all to their email for whatever reason.
A third option is to unlock after a set time. The problem is that you create a race condition for the user and the attacker. It’s more likely the attacker will win as they’re using bots to get in the account. This would keep the user perpetually locked out as the attacker will always win the race. You can’t change your master password if you can never get into your account thus helping the attacker to get even luckier.
You also have the issue of a vindictive spouse who knows your master password but doesn’t have your 2FA. They could keep logging in and trigger it to lock your account to keep you out. They may even have access to your email and change the password to keep you from unlocking it.
Using captcha after so many failed attempts seems to be the best solution. A normal person will never be able to guess all possibilities of the 2FA code in 30 seconds. A bot would be stopped from guessing after so many failed attempts and would get too costly to keep guessing. While the user gets the warning email without being locked out so they change their master password.
There are many other ways to do it beyond the ones you mention. My favorite is to suspend the account, email or text the user with a temporary password to get back in, and then ask the user “secret” questions that they must answer to reset the password at login (like what was your first concert or the first name of your high school sweetheart, etc.). Lots of organizations use this approach.
I think the captcha approach would be a huge improvement, but I agree with @cristianlivella that I would feel much safer if my account were suspended entirely on an intrusion.
I don’t feel comfortable with security questions as people often pick very bad ones and something else to keep track of. I don’t want the strength of my 2FA to come down to “what was your first car”, it kind of defeats the point of 2FA.
The problem with locking an account is that it needs to be unlocked but how do you do that without keeping the legit user out? Using a captcha is the best option I’ve seen so far. The last thing I want is to be locked out permanently because the attacker can abuse the system.
I know maybe not relevant to this particular discussion, but I have a workaround for this:
I use Duo as 2FA provider which lets me have per user blocking after too many failed attempts. With duo I can either use
Duo push to authenticate without typing/copying passcodes
Duo mobile passcode, witch is similar to OTP generated passcodes but more secure as you can use one passcode only once.
Furthermore I can set up a maximum failed authentication limit, so after let`s say 10 failed attempts the user gets blocked for e.g 3 hours or until a duo administrator unblock (via duo admin panel). Duo has a reasonable free plan with somewhat limited functionality, but still usable.