-
Notifications
You must be signed in to change notification settings - Fork 983
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mandatory 2FA with existing users without 2FA vulnerable to account takeover #11850
Comments
To be clear, the basic path of compromise here is:
|
Enumerating some of the individual items needed to address this:
(Let me know if I got any of these wrong!) |
We probably also need:
Conceptually the right way to think about requiring 2FA for a Project (or Organization if we do it there) is not that we need to check at authorization whether a user has 2FA, because that's a mutable property and can change, but rather we need to ensure that no user without 2FA has any sort of permission to do anything, nor can they gain permission without someone with 2FA explicitly granting it to them. Any sort of ambient authority that's just laying around waiting for that user to take some general action, is authority that isn't meaningfully restricted since an attacker could that that action themselves. |
An interesting thing here, if you block inviting a user if they don't have 2FA, that lets you use invites to a project as an oracle to determine if a user has 2FA or not. What GitHub does here is they let you invite users to an organization regardless of their 2FA status but you cannot accept an invite unless you have 2FA enabled. This technically has the same problem above, that any unaccepted invites to a user without 2FA enabled is a possible liability since it's a form of ambient authority that's just waiting for the user to add 2FA to their account to claim it. However, GitHub tempers this by making invites only valid for 7 days so that ambient authority is limited in time, and since our project invites are limited to valid for 3 days, we could do a similar thing. |
Closing now that 2FA is required for all users. |
Re-opening this, mandatory 2FA does not solve this unless we invalidate all existing credentials. |
Or rather, the general problem of "there's still ambient authority out there vulnerable to ATO" still exists, it's just no longer specific to projects that choose to require 2FA, it's now all projects on PyPI. |
In April 2024 all unenrolled users had their email addresses unverified due to an ATO attack. https://blog.pypi.org/posts/2024-04-03-user-account-access/ The credentials themselves haven't been invalidated, but in order to take over an existing account, you'd also have to obtain email account access to perform verification and then enroll in 2FA. |
Users are currently able to add a 2FA device to their account and the intention is that in the future, a user account with 2FA added will require using an API token to do uploads (#7265).
In addition to that, projects are able to require 2FA (or may have this requirement applied to them by PyPI) which would mean that users will end up in a situation where they may sometimes require 2FA but not always. Specifically, if a user has not added a 2FA method to their account, but there are projects they are on that requires 2FA, they won't be able to manage that project because they're not logging in with 2FA but they can do other things on their account.. like create API tokens.
So that means that we end up with a gap here, where a user could opt not to add 2FA to their account, be on a project that requires it, then if their account gets compromised that compromised user could create API tokens which are good until revoked, even if someone later adds 2FA, or even add a 2FA method of their own to the account.
We have two distinct cases for requiring 2FA at the project level:
But in terms of this gap, you can really narrow the question down to just:
How do we handle existing users on a project when they don't have a 2FA method on their account, but one of their projects starts to require it, for any reason?
I took a look at what GitHub does for organizations that toggle require 2FA on, and they have a big call out that enabling mandatory 2FA will boot anyone from the organization that doesn't have 2FA enabled, and thinking through it, I can't think of a good way of implementing mandatory 2FA, without this flaw, without removing all users from the project that don't have 2FA enabled on their account OR locking them out of their account completely.
For (1) above, going into the future we can either do what GitHub does and boot everyone from the project that doesn't have 2FA enabled or we can prevent toggling the required 2FA flag if any user on the project does not have a 2FA method attached to their account.
For (2), I don't really know what the right answer is. During the transitional period it's fine to leave them alone, but eventually to actually get the benefits of mandatory 2FA, they're going to have to either have their account locked out OR they're going to have to be removed from any projects that require 2FA (and that opens up a whole can of worms about what if they're the only person attached to that project). The same is true for any project in group (1) that have enabled mandatory 2FA that have existing users without 2FA attached to their project.
Addition to the above, the toggling of a project from not requiring 2FA to requiring 2FA is not the only avenue for users without 2FA to get attached to a 2FA requiring project. Off the top of my head, I can think of:
Basically, I think to actually implement mandatory 2FA in a way that is safe from account takeover, you cannot have any user associated with that project, through any means, that does not have 2FA enabled on their account.
We're in a transitionary period, so we'll have to manage this process, but at a minimum we should "stop the bleeding" where possible while we figure out how to cope with this requirement (or figure out if I'm wrong!), but going forward we're always going to have the potential to have a project in this same transitional state anytime (2) triggers a new project to transition from not requring to requiring.
The text was updated successfully, but these errors were encountered: