NOTE: This is a copy and paste of an issue opened in https://security.drupal.org that didn't turn out to be a security issue.
This module has an access bypass vulnerability.
https://www.drupal.org/project/simple_oauth/issues/3044428
Problem/Motivation
I have a decoupled Drupal site using this module for authentication. All users log in from a single site which uses the /oauth/token endpoint to authenticate the users. The Drupal site is configured with a single Consumer entity whose "scopes" are configured to all the roles on the Drupal site (since all users log in through this method, aside from some administrators, all the roles need to be available). It all seems to be working well, except for one thing. When a user who only has some of those roles authenticates using simple_oauth, the access token generated by the module actually has all of the "scopes" associated with it rather than only the ones that the user actually has.
Example: If Jenny has the "author" role, and the Consumer is configured with roles "author", "banker", and "cobbler" as scopes, then when Jenny authenticates the token has all three of those roles, and when she makes Rest service calls, \Drupal::currentUser() shows her as having all of those roles. When in actuality she should only have the one.
Proposed resolution
When a user authenticates using Simple OAuth, the only roles and permissions exposed by \Drupal::currentUser() should be ones in scope of the Consumer and which the authenticated user actually has associated with their account.
The culprit seems to be simple_oauth/Repositories/ScopeRepository::finalizeScopes(), the end of which seems to be very intentionally adding all of the scopes/roles configured on the Consumer and adding them to the access token regardless of the user's actual roles. This seems like it is what's leading to the unexpected behavior.
| Comment | File | Size | Author |
|---|---|---|---|
| #3 | 169749--unprocessed-roles--5.patch | 18.71 KB | e0ipso |
| #2 | 169749--unprocessed-roles--2.patch | 2.78 KB | e0ipso |
Comments
Comment #2
e0ipsoInitial patch shows promising results.
Comment #3
e0ipsoThis are the tests with some fixes.
Comment #4
e0ipsoI have implemented the fix for the claimed security concern. However I don't feel comfortable with this change.
I consider this to be a useful feature, maybe it could be better communicated, but it is documented here https://youtu.be/-xRBJvmg0qQ
The idea is that Simple OAuth site builders should create an ad-hoc role (or collection of roles) when creating a consumer, that any user can gain access to provided they know both the client ID and client secret. If a user wants to request additional roles they can do so.
In summary, with the current feature set (without this issue's patch), a user request can gain access to these roles:
- Any role the user already has configured in Drupal. This is protected with Drupal's username/password (or session).
- Any role the consumer has configured in Drupal. This is protected with the consumer's id/secret. While this is the same for all the users of a given app, this is distributed with the app and the user has no knowledge of it.
The only place where client secret is not required is when using the implicit grant (https://oauth2.thephpleague.com/authorization-server/implicit-grant/). However this is marked as insecure in Drupal and disabled by default. In order to enable it you have to declare you understand the security implications.
The question for the reporter and the security team is: do you think this is a sufficiently secure system? (you may have different expectations, but the question is about security)
Bear in mind that shipping the patch above implies a new major version + unpublishing old versions + code changes to the 3rd party apps that integrate with this module.
Comment #5
e0ipso#8 greggles commented
Comment #6
e0ipso#9 JKerschner commented
Comment #7
e0ipsoHmm, I feel that the documentation is pretty accurate. There have been several minor improvements along the way after the videos have been recorded, but all the major concepts still stand accurate.
@greggles we could add more extra verbose documentation in the checkbox on the form explaining the implications of assigning a role to a consumer.
Comment #8
e0ipsoAlso, based on the conversations. Can we make this issue public again?
Comment #9
e0ipso#14 greggles commented
Comment #10
e0ipso#16 mlhess commented
Comment #11
gregglesReplying to #7 here, @e0ipso, that idea seems great to me. Thanks for posting this with such good context from the private issue. That is hopefully helpful to folks to know the history of the issue.
Comment #12
Niko9911 commentedFur sure the intended way cannot be, if user is not assigned to have x role, he will still get it if he just logins by using exact consumers. In this case it also means if you have role based oauth consumer, you will allow users to have roles which they dont have in reality.
I have already proposed patch for this in https://www.drupal.org/project/simple_oauth/issues/3082516.
In any case, this kind of feature cannot be in a design as it makes the authentication process insecure!
Comment #13
e0ipsoThis feature set is consistent with the OAuth 2 specification. You can read more at https://tools.ietf.org/html/rfc6749#section-3.3.
This behavior is by design. It's so consumers can ensure access to certain necessary resources. The question is why are you giving more access to the consumer than what you intend?
The team of security experts that looked at this do not agree with that statement. I do not agree either. I just think that your setup needs to be fixed. It's like granting
administer site configurationto anonymous users, that's not a security issue with Drupal core it's a configuration choice.I hope this clarifies things. I also see you are new in the community that's why I took part of my free time to respond to your concerns in more detail. Please, remember that mindfulness in communication style is appreciated when dealing with vonluneers.
Comment #14
joelstein commentedI read the text from that specification and saw this paragraph:
I think the spec provides room to limit the Drupal roles which are actually granted from the requested scopes. And I think we should do this because it's intuitively what you would expect based on how Drupal roles are normally used.
Comment #15
e0ipsoThis may be a common opinion, however this issue has been posted for a long time but there is no real traction to change things.
I am of the opposite opinion, I think that you should be able to specify the required permissions for the application to work. If you want that to be 0 permissions, you can do so very easily by configuring your consumer with a role empty of permissions.
Comment #16
bradjones1I'm going to be bold and close this as works as designed. I concur with Matteu in general, and this has been open for a long time without others chiming in. Personally I believe that designing an authentication/authorization regime for any application requires the site owner to understand and validate the implementation for themselves. I don't see anything here that is out of spec compliance by a strict reading. (The scopes claim may need a name update, but that's already ticketed on #3247846: [BC break] Rename scopes to scope in JWT payload)
Comment #17
idebr commentedFor anyone bumping into this issue from external search engines: this behavior has changed in 6.0.x and access checks now performed against both the token (scope) and the subject (user). This was implemented in #3263631: Create dedicated authorization server service and implement new (scope/consumer) data model