Injection of NEL headers in Maven dependency proxy response allows attacker to spy on victims browsers activity, leading to ATO abusing OAuth flows

⚠️ 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 #3016623 by joaxcar on 2025-02-27, assigned to GitLab Team:

Report | Attachments | How To Reproduce

Report

Summary

Hi team,
This is very similar to #2813673 but targets the Maven dependency proxy. The injection does work on gitlab.com, but has almost no impact, the real impact exists on self hosted instances that utilises any form of caching other than Cloudflare

The Maven dependency proxy allows an attacker to set NEL(Network Error Loggin) policys in a victims browser. See the previous report for details on attacking using NEL headers. The short version is:

When a NEL policy is set in a browser for a domain, this browser will send ALL full visited URLs to the attackers server indefinitely. This can lead to ATO by abusing OAuth flows for example, it can also leak access tokens used in URLs using the private_token URL parameter.

Requirements

I put attack complexity to high here as this attack requires the target server to actually use a cache (other than Cloudflare). Gitlab.com does use a cache, but as Cloudflare uses its own NEL headers, the attack will fail after the initial setup as any other request to gitlab.com will set a new NEL policy. This incidental protection does not exist on other cache providers such as Google and Fastly.

NEL

Quick note on NEL headers. These headers only work on Chromium-based browsers (all their brands). Whenever a Chromium-based browser handles a response from a server that contains these two headers

Report-To: {  
     "group": "default",  
     "max_age": 99999999,  
     "endpoints": [{  
         "url": "https://example.com"  
      }]  
}
Nel: {  
    "report_to”: "default",  
    "max_age": 999999,  
    "success_fraction": 1.0,  
    "failure_fraction": 1.0,  
}

The browser will start to send NEL reports to https://example.com, and as the two fraction options are set to 1.0 it will send reports on ALL requests.

When the NEL header is first set in the browser, it will not get removed until another NEL policy is set or if the victim vipe all browser data. This means that once it it place it will stay there and leak user info indefinitely (there is no limit on the max_age)

A NEL report contains the full URL of all requested pages.

POC

I will just prove that setting the headers work on gitlab.com as setting up caching is quite cumbersome, full examples of attacks was proven in #2813673. If you need me to set up a complete vulnerable server I can come back and do that.

  1. Host this script on a server reachable from the internet (make sure to replace the catch server with a server that can handle NEL. It must allow CORS. Use for example webhook.site and configure it for CORS) nel.py
  2. Create a new Ultimate trial on Gitlab.com
  3. Create a new project in the new Ultimate group, take a note of the project ID
  4. Go to https://gitlab.com/GROUPNAME/PROJECTNAME/-/settings/packages_and_registries
  5. Enable Dependency Proxy and enter your URL from step 1 in the URL input. Leave the other fields blank. Click save
  6. Now go to https://gitlab.com/-/user_settings/personal_access_tokens and create a new api access token
  7. Run this command in a terminal (replace , and <PROJECT_ID>
curl -X GET -k --fail-with-body --verbose "https://<USERNAME>:<TOKEN>[@]gitlab.com/api/v4/projects/<PROJECT_ID>/dependency_proxy/packages/maven/new/bypass"  

This will cache the response
8. Visit this in Chrome (replace <PROJECT_ID>): https://gitlab.com/api/v4/projects/<PROJECT_ID>/dependency_proxy/packages/maven/new/bypass
9. Look at your catch server and see that you will soon get a NEL report showing that the NEL policy is set

As mentioned as soon as you visit another route on gitlab.com the NEL policy will get replaced. But on a self hosted instance your browser would now start sending reports on ALL URLs visited.

What is the current bug behavior?

NEL headers are proxied on the Maven dependency proxy endpoint

What is the expected correct behavior?

As with the k8s proxy NEL headers should be removed from proxied requests

This video just shows an endpoint on gitlab
https://gitlab.com/api/v4/projects/66166935/dependency_proxy/packages/maven/new/nel
that will serve my NEL headers. if you visit it I should get a report from your browser

Screen_Recording_2025-02-27_at_13.17.36.mov

Impact

Injection of NEL policies in victims' browsers leaks browser session data and, in the end, leads to full ATO of victims' gitlab accounts.

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

How To Reproduce

Please add reproducibility information to this section: