Insufficient OAuth Revocation
HackerOne report #892427 by benaubin
on 2020-06-05, assigned to @jbroullon:
Summary
When a user revokes OAuth access to an app, access grants are not revoked. Generally, access grants have a 10 minute lifespan and are revoked upon use (with proper locking - I've verified - to prevent race-conditions implemented by Doorkeeper). This would theoretically make attacks difficult, however, an application may silently send a user through the authorization flow any time after first authorization, making this significantly more plausible.
For example, imagine a user browsing a third party site, then noticing something fishy (maybe a privacy policy). The user decides to revoke GitLab access to that app, but before closing the tab - or maybe when visiting another page on the site, is sent through the OAuth authorization flow. The 3rd-party site can store the grant and redeem it any time in the next 10 minutes.
If that user revokes the 3rd-party app's access less than 10 minutes after going through an authorization flow, the third-party app can silently reauthorize.
Steps to reproduce
Perform an authorization code flow, as usual.
- Start an authorization flow (send the user to /oauth/authorize).
- Redeem code for access token (POST /oauth/token).
- Send the user back to /oauth/authorize. As they have already authorized the user, they likely won't notice this redirect.
- This time, don't redeem the code for an access token, store it for later use.
- Send the user to their expected destination.
- As the user, use /oauth/applications on GitLab.com to revoke the application's access.
- Within 10 minutes of step 3, redeem the stored authorization code for a new access token
Cause & Fix
When a user revokes access to an OAuth application, only access tokens are revoked.
Current implementation (app/controllers/oauth/authorized_applications_controller.rb#L19).
Doorkeeper::AccessToken.revoke_all_for(params[:id], current_resource_owner)
Add a line to revoke access grants:
Doorkeeper::AccessGrant.revoke_all_for(params[:id], current_resource_owner)
Other recommendation
Send "third-party app connected" emails when an OAuth app is connected, to help mitigate the risk of an app silently gaining access to a user's account. This gives users the ability to spot fishy things occurring after-the-fact.
Impact
A third-party app can silently regain OAuth access to user's account after revocation, if that user visited the third-party's site at all, including through an invisible redirect, in the 10 minutes prior to revocation.