3 ms·
tl;dr: The code should verify the user's second factor before the user's password. Consider this, scenario A: 1. When attacker enters a username and bad passw
by ezekg 4y ago
tl;dr: The code should verify the user's second factor before the user's password.
Consider this, scenario A:
1. When attacker enters a username and bad password. then they receive a bad password error.
2. When attacker enters a username and good password, then they receive a 2FA prompt.
And then scenario B:
1. When attacker enters a username and bad password, then they receive a 2FA prompt.
2. When attacker enters a username and good password, then they receive a 2FA prompt.
In scenario A, the website leaks password validity to the attacker. In the case of a brute force attack, the attacker can use the 2FA prompt as a signal that they found a good password. Scenario B does not leak that information, because the second factor was wrong or missing.
More concretely, this pseudo-code:
if user.authenticate_with_password(password)
if user.authenticate_with_second_factor(code)
# ...
else
raise InvalidSecondFactorError
end
else
raise InvalidPasswordError
end
Should instead be this pseudo-code:
if user.authenticate_with_second_factor(code)
if user.authenticate_with_password(password)
# ...
else
raise InvalidPasswordError
end
else
raise InvalidSecondFactorError
end
Hope that makes sense. :)
- Eleison23 4y agoBut which 2FA prompt should they receive? If MFA can be configured using myriad choices, should a user be prompted to "Insert security key" or "Input security code" or "Send code to your email/SMS" or "Tap YES on your mobile device"? Since you can't know a priori what the second factor will look like, I'd say it's troublesome to try and present a challenge to every user regardless of their MFA configuration.
- BeefWellington 4y agoNote that this is not universal to all systems. If your 2FA options all require the user to enter a code, you can simply display a "Please enter your 2FA code" dialog without divulging what kind of 2FA the user has.
- dalmo3 4y agoHow would you prevent someone from spamming a user just by knowing their username? Say, if the 2FA is done by SMS, or email. An attacker brute-forcing the password could flood the user with multiple messages. The usual response is doing a password reset, but that wouldn't work in your system. I wonder how systems that use magic links handle this.
- ezekg 4y agoYour authentication system should have per-user and per-IP rate limits.
- Tangurena2 4y ago> How would you prevent someone from spamming a user just by knowing their username? Wasn't something like this how Uber got hacked recently? Spamming the target until they clicked "yes" on the 2FA prompt?
- ezekg 4y agoIn my pseudo-code example, we're raising a couple errors, InvalidSecondFactorError and InvalidPasswordError. You could imagine there could be finer grained errors, such as TotpRequiredError or HardwareKeyRequiredError, depending on the user's second factors, which could then propagate down to the UI via specific error codes. The UI could then use these error codes to display the correct prompt, and then resend the request with the appropriate second factor.
- nick__m 4y agoYou would have to randomize the error when the wrong password is inputed and ensure that for a particular username the returned error is invariant. Else an attacker could infer that when you get a different error you have a correct password.
- ezekg 4y agoThe bad password error would only be sent if the second factor is valid, though.
- ridgered4 4y agoIt sounds good for stopping attackers, but if I am the real user and enter a bad password it is going to be pretty infuriating spending time troubleshooting the 2FA not working problem that doesn't actually exist. I suspect your service will get a reputation for completely unreliable 2FA which may have unintended consequences.
- codegeek 4y agoThis can be solved with an error message at the end with something like "You either provided an incorrect password or your 2FA code is incorrect. Check and try again". This still ensures that someone is not able to guess the correct password and reuse it somewhere else where 2FA may not be enabled.