Productivity analytics endpoint doesn't enforce properly tier check
HackerOne report #707375 by rpadovani on 2019-10-03, assigned to @cmaxim:
Summary
The new Productivity Analytics feature should be available only to Premium or higher accounts.
The endpoint to retrieve data for the feature, however, doesn't properly authenticate the user, allowing any user to retrieve the data, making the feature easily available to anyone.
However, there isn't any leak of confidential data, because the users retrieve only data that they could already retrieve, if they had paid.
It is just an unauthorized access to paid resources.
Steps to reproduce
- The endpoint
/-/analytics/productivity_analytics, when queried for a JSON reply using theAcceptheader, returns data in the JSON format. If you do not specify anything, it returns the HTML page. - The endpoint authenticates the parameter
group_idandproject_id. That is, it checks the group or the project has at least a premium license. - If you do not specify nor the
group_idor theproject_id, the endpoint just executes the query. - In this way, you can access all the data needed to do the analytics. You can also access public data of other projects that are not usually easily accessible.
- Since a lot of parameters are accepted, it is easy to customize the search to return only the MR of a project that is not under the premium license. E.g: using the
my_reaction_emojiparameter.
Here the list of accepted parameters:
-
scope: 'created_by_me' or 'assigned_to_me' or 'all' -
state: 'open', 'closed', 'merged', 'locked', or 'all' -
milestone_title: string -
author_id: integer -
assignee_id: integer -
search: string -
in: 'title', 'description', or a string joining them with comma -
label_name: string -
sort: string -
non_archived: boolean -
my_reaction_emoji: string -
source_branch: string -
target_branch: string -
created_after: datetime -
created_before: datetime -
updated_after: datetime -
updated_before: datetime
Impact
Users can access a premium feature for free without any difficulty (a proxy or a browser plugin would work well enough)
Examples
This is an example of a fetch request made from the console, so with the cookies:
a = await fetch("https://gitlab.com/-/analytics/productivity_analytics?scope=created_by_me", {
"credentials": "include",
"headers": {
"Accept": "application/json, text/plain, */*",
"X-CSRF-Token": "token",
"X-Requested-With": "XMLHttpRequest"
},
"referrer": "https://gitlab.com/-/analytics/productivity_analytics",
"method": "GET",
"mode": "cors"
});
await a.json()
The response is an array of 20 objects with all the data needed by the feature
What is the current bug behavior?
I can query the productivity_analytics endpoint without specifying group_id nor project_id
What is the expected correct behavior?
group_id or project_id are required, and they are used to check I am allowed to access the resource
Output of checks
This bug happens on GitLab.com
Impact
Users can access a premium feature for free without any difficulty (a proxy or a browser plugin would work well enough)