New Relic: Disclosure of locally served nerdpacks due to nr-local.net CORS policy misconfiguration

2019-11-26T18:03:29
ID H1:746786
Type hackerone
Reporter skavans
Modified 2020-08-13T13:31:07

Description

Hey team,

I've discovered that webserver which serves NR1 nerdpacks locally (after nr1 nerdpack:serve is executed) allows cross-origin requests from every subdomain of nr-ext.net. Since the nr-ext.net domain is used as a sandbox for user-supplied apps, an attacker can place there a malicious code that requests the data from a victim's local webserver. Then, when a victim visits the attacker's website, the following data can be transmitted to the attacker: * the nerdpacks', nerdlets' and launchers' IDs, which are serving locally at the user's workstation; * all corresponding artifacts (app source code, HTMLs, JS scripts, etc.); * information needed to connect to websocket live source code updater (not tested).

I'm in doubt about the severity of this issue, because I don't know whether you assume the under-develop apps source code as confidential data. In the same time, I tried to use the disclosed nerdpack ID for doing something more severe, but with no success. You specify that app's ID is used to get access to the corresponding account data, but I wasn't successful with it. So I kindly ask you to determine the severity at your side. I've spent a lot of hours to escalate this further, but the ideas are over :)

Steps to reproduce

The nr-ext.net is used as a sandbox for running a user-supplied reactJS apps. NR1 creates an iframe pointing to something like https://266bd739-2dfd-42e4-b000-be6ac0449ec9.g0.nr-ext.net/?nerdpacks=local&use_version=d19c5d29, which loads an app in its turn. But, if I just navigate to this URL with browser, the app is not loaded, it works only if it's loaded inside an iframe on NR1 (because of supportive code placed there, I think). That's why it's difficult to force a victim to visit my own app located at nt-ext.net. So, to exploit this successfully, I had to copy a part of one.newrelic.com supportive code to my own domain and then load my own malicious app through iframe, as the legal one.newrelic.com does. So to reproduce this, you should either deploy all my complicated webserver somewhere or just use the one served by me at xn--1xa.su.

First, you will need to serve some nerdpack locally. 1) Install nr1 CLI at Ubuntu OS or macOS using a man from https://one.newrelic.com/launcher/developer-center.launcher 2) Add some profile using the same man. 3) Create a new nerdpack somewhere with nr1 create. You can select default options further. 4) Navigate to the new nerdpack's dir and serve it locally with cd your-nerdpack && nr1 nerdpack:serve. You should see the following if everything is OK: {F644364} 5) Navigate to https://a.nr-local.net:9973/nerdlets. This is data, which can be stolen by the attacker's website with iframe pointing to a malicious app inside.

Here you can just visit my own malicious website at http://xn--1xa.su:8888/launcher/2ee6d947-95f3-4b4b-97c9-a49fe01840df.my-launcher#launcher=eyJ0aW1lUmFuZ2UiOnsiYmVnaW5fdGltZSI6bnVsbCwiZW5kX3RpbWUiOm51bGwsImR1cmF0aW9uIjoxODAwMDAwfX0=&pane=eyJuZXJkbGV0SWQiOiIyZWU2ZDk0Ny05NWYzLTRiNGItOTdjOS1hNDlmZTAxODQwZGYubXktbmVyZGxldCJ9&state=IjE5QkMxNDVGLUEzNUEtMUM5OC1DMTQ4LUREMUY1NTM2QTIyNCI= to see that the data you've seen at step 5 is available for reading by this malicious website: {F644369}

Or, you can deploy this malicious webserver at any your domain and test this there: 6) Extract a content of {F644370} somewhere 7) Install python dependencies with sudo pip install tornado 8) Run a server with python server.py 9) Navigate to http://<YOUR_IP_OR_DOMAIN>:8888/launcher/2ee6d947-95f3-4b4b-97c9-a49fe01840df.my-launcher#launcher=eyJ0aW1lUmFuZ2UiOnsiYmVnaW5fdGltZSI6bnVsbCwiZW5kX3RpbWUiOm51bGwsImR1cmF0aW9uIjoxODAwMDAwfX0=&pane=eyJuZXJkbGV0SWQiOiIyZWU2ZDk0Ny05NWYzLTRiNGItOTdjOS1hNDlmZTAxODQwZGYubXktbmVyZGxldCJ9&state=IjE5QkMxNDVGLUEzNUEtMUM5OC1DMTQ4LUREMUY1NTM2QTIyNCI= and make sure the app is allowed to see the data you've seen at step 5.

Remediation

The root cause of this issue is misconfigured CORS policy at local nerdpack server. Every published nerdpack is placed at its own associated subdomain of .nr-ext.net. But, every origin ending with .nr-ext.net is allowed to read the data from nr-local.net, that allows other users' apps to read a victim's local server data.

Here are vulnerable code lines of 3pp-cli-nerdpack-serve/src/ws/Orchestrator.js local nerdpack server: js app.use( cors({ origin: (origin, callback) => { if ( !origin || origin.endsWith('.newrelic.com') || origin.endsWith('.nr-ext.net') ) { callback(null, true); } else { callback(new Error('Not allowed by CORS')); } }, credentials: true, }) );

You should make sure here that the subdomain of nr-ext.net is the same as the requested subdomain of nr-local.net, not just allow all subdomains of nr-ext.net.

PoC video

{F644376}

Please let me know if you need some assistance to reproduce or mitigate the issue.

Impact

Disclosure of: * the nerdpacks', nerdlets' and launchers' IDs, which are serving locally at the user's workstation; * all corresponding artifacts (app source code, HTMLs, JS scripts, etc.); * information needed to connect to websocket live source code updater (not tested).