How MembershipReboot mitigates login and two factor authentication brute force attacks
Login Brute Force Attacks
A complete security solution involves prevention, detection, and reaction. This means that you need to protect what’s sensitive in your system, but that’s not sufficient. You also need to actively monitor for attacks on the system and when you detect an attack you need to react to mitigate the attack. Schneier would be proud of me for saying so.
This basic tenet for building security solutions should apply when building an identity management solution. It’s not hard at all for an attacker to build tooling to mount an automated attack on the login page for a web application. And so how many of you write code to detect this scenario, let alone react to it? Well, I’d argue you shouldn’t have to. My contention is that this should be an obvious feature provided by any identity management library.
What is sensitive are the users’ passwords, and what is needed is a detection and mitigation approach for an attacker attempting to brute force a user’s password by repeated guessing against an application’s login page (which is different than the offline attacks I previously wrote about).
MembershipReboot does this — it keeps track of the number of failed login attempts as well as the last date/time the user failed to login. In its authentication logic, if the user attempts to login and the number of failed login attempts is above a reasonable threshold (which is configurable but defaults to 5) and is within a reasonable lockout duration (which is configurable but defaults to 5 minutes) then authentication fails (even if the credentials are correct). In short, after 5 failed login attempts within 5 minutes, MembeshipReboot locks the user out of their account. This is crucial for mitigating against these brute force attacks against the login page of an application.
Additionally, MembershipReboot (via it’s event bus architecture) raises an event to the application when an invalid login attempt was made and it passes the number of failed attempts. This allows an application to take further mitigation measures (e.g. blocking the user’s IP address) as deemed appropriate.
Unfortunately, nothing like this is provided in Microsoft’s current ASP.NET Identity solution (neither the detection, prevention nor notification) without deriving and replacing their security implementation. This means (by default) it’s wide open to such an attack.
Two Factor Authentication Brute Force Attacks
Another attack related to password brute force attacks is two factor authentication code brute force attacks. Some authentication systems support two factor authentication where after a user authenticates with a password, they then have to enter a code that is sent to their mobile phone. This is yet another point for attack, and as such, if the identity management solution supports two factor authentication then it should also mitigate against brute force attacks against the verification code.
MembershipReboot does this as well — it mitigates against this in two ways: 1) Once the user authenticates with a password the user is issued a short-lived authentication cookie (which is configurable but defaults to 5 minutes). This means the attacker only has 5 minutes to enter the mobile code before they must start over again. The other mitigation is 2) MembershipReboot uses the same tracking mechanism for codes that it uses for passwords as described above. This means that (by default) a user has 5 attempts to enter the verification code before they are locked out. This is crucial because two factor authentication codes have a much smaller search space than passwords (since they’re typically a numeric code with 5 or 6 digits).
Microsoft’s ASP.NET Identity does implement the short-lived authentication cookie, but it does not implement the brute force prevention for the code itself. In my rudimentary attack tests, I was able to attempt ~200K codes in the 5 minute window. If we assume my tests were in an ideal network, we can guesstimate that in a real network an attacker could make half of the attempts my test showed (so say ~100K). This is a 10% success rate, which just means an attacker needs to try a few more times and they’ll be able to compromise the account. This is less than ideal and far too high of a success rate for the default implementation and configuration.