Page MenuHomePhabricator

Strengthen two factor authentication by making it concurrent instead of sequential during the authentication process
Open, MediumPublic

Description

Two factor authentication increases security by requiring both the known passphrase and a temporal challenge response. Combined, this increases the authentication security significantly.

However, the current implementation collects authentication information sequentially instead of concurrently.

This scheme reduces the overall strength by allowing attackers to attempt to compromise the passphrase and the temporal challenge as separate steps - as the passphrase component reveals if it is matched prior to moving to the second factor.

Event Timeline

Suggested implementation would be to collect all authentication information simultaneously (userid, passphase, 2FA response). For accounts without 2FA enabled, simply ignore any (including null responses) to the challenge response.

Say, a user doesn't have javascript enabled. We can't dynamically add/remove the OTP field from the form. But what if a user doesn't have JS enabled, do we show it by default? Or not? Do we risk confusing the user who's going to then go "WTF is this?".

Do we annotate to only fill it in if they know they need to? How would some users know if they do need to?

Aren't we then also complicating the workflow?

And if JS is enabled we've got to expose something probably in the API as to whether the user has OATHAuth enabled... Which feels like an attack vector waiting to happen... You could easily make a list of all users on a wiki with it enabled (or not), and then discard the ones that do, as not worth the effort to attack...

Note that this was achieved in https://gerrit.wikimedia.org/r/280672, so maybe this is more a bug with AuthManager than it is this extension?

Say, a user doesn't have javascript enabled.

The proposal as I see it (and as it was originally implemented in the aforementioned patch) was to keep the same two-page UI workflow, but simply not check the password until the user enters their OTP. This was achieved by literally dumping the contents of the login form into session storage. Of course, something more sophisticated (preferably with encryption) would be better.

I'm not too picky on the "how" as long as the result is that information on if the password was correctly guessed is not revealed. Similarly, the authentication failed error message should not be different for bad token vs bad password vs bad both.

I would not expect that adding an (Optional) OATH code: field to the initial credential page when this extension is enabled would be too confusing.

The proposal as I see it (and as it was originally implemented in the aforementioned patch) was to keep the same two-page UI workflow, but simply not check the password until the user enters their OTP. This was achieved by literally dumping the contents of the login form into session storage. Of course, something more sophisticated (preferably with encryption) would be better.

This of course is equivalent to exposing whether or not the user has OATH enabled, since an attacker could just use a dummy password and then see if they get an OATH prompt.

I would not expect that adding an (Optional) OATH code: field to the initial credential page when this extension is enabled would be too confusing.

"You must be new around here"

:D

This of course is equivalent to exposing whether or not the user has OATH enabled, since an attacker could just use a dummy password and then see if they get an OATH prompt.

Except the goal is not to protect the user's OATH enrollment status, which does not matter and is not secret. The goal is to make an incorrect password indistinguishable from an incorrect OATH code by not attempting to authenticate until all the necessary secrets have been collected.

I would not expect that adding an (Optional) OATH code: field to the initial credential page when this extension is enabled would be too confusing.

Speaking from when wikitech (a wiki intended for developers) had an extra "domain" field that was optional, and people would get pretty confused about it, I think an acronym that most people don't know about shown to non-technical users would be extremely confusing.

This of course is equivalent to exposing whether or not the user has OATH enabled, since an attacker could just use a dummy password and then see if they get an OATH prompt.

Except the goal is not to protect the user's OATH enrollment status, which does not matter and is not secret. The goal is to make an incorrect password indistinguishable from an incorrect OATH code by not attempting to authenticate until all the necessary secrets have been collected.

Agree. Was just throwing a suggestion earlier, this is the actual goal of my request, not to leak pass/fail information on the passphrase step.

This causes all kinds of complications for very dubious benefits. What if the user mistypes the password? You'll have to keep that secret and say something vague like "either the password or the two-factor key was wrong" and they are left guessing whether they are misremembering it or something is wrong with their key generator device. Users with a long password probably won't appreciate having to retype it every time they make a typo in the second factor. What if the password is handled, by - say - LdapAuth? The OATH extension would basically have to implement its own auth manager, call the password provider, stash the result, pretend it's a success and return the real result after the second factor was submitted. What happens if the user does not exist locally (which secondary providers are not prepared for)? If you want to hide the success of the login, you have to autocreate the user even if the password was wrong.

I agree with what @Tgr said and want to also note: What happens, if OATHAuth is not the only Secondary provider, which requires, for some users, more input data? In the worst case, you get multiple input boxes on the login form, which are only meant for a specific, different, subset of the users using the wiki, depending on if a specific security feature is enabled for an account or not.

Technically it shouldn't be a big problem (as far as I can see) to convert OATHAuth into a Pre-auth extension, like ConfirmEdit is, and show the input on the login form directly, however, with all the problems mentioned already need to be handled.

Also, for all other sites I use, the one-time token is requested, after I provided the correct login data (username/e-mail and password), which, of course, doesn't mean, that this is the only and best solution :)

Aklapper renamed this task from Strenthen two factor authentication by making it concurrent instead of sequential during the authentication process to Strengthen two factor authentication by making it concurrent instead of sequential during the authentication process.Aug 20 2017, 11:19 AM

Technically it shouldn't be a big problem (as far as I can see) to convert OATHAuth into a Pre-auth extension, like ConfirmEdit is, and show the input on the login form directly

Preauth providers run before the primary authentication could happen, so they do not have reliable knowledge of the user's identity. Secondary providers can show up on the iniital form the same way preauth providers do, though, so that part is not problematic. But you would still learn from error message which provider failed, short of some really horrible hacks.

This is only with the current coding. I've used other 2FA systems such as RSA's token system, the logon screen has multiple boxes: userid, tokenPIN/tokenCode, password, realm. Failed logons for any reason all present the same error.

chasemp triaged this task as Medium priority.Dec 9 2019, 5:20 PM