Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PNA permission prompt implementation bug in Chrome 121 with relevance for user security and privacy #126

Open
DanielBaulig opened this issue Jan 28, 2024 · 8 comments

Comments

@DanielBaulig
Copy link

DanielBaulig commented Jan 28, 2024

In my other issue #117 I had flagged in November that I believe there to be a bug in the implementation of the Private Network Access Permission dialog that allows for mixed content requests to be sent to private network hosts without a permission dialog under certain circumstances involving a service worker. Since Private Network Access is available to any origin through it's Origin Trial, this bug could at this point be exploited in production by any origin choosing to participate in the Origin Trial.

I'm copy & pasting the steps to reproduce the issue here:

self.addEventListener('fetch', (event) => {
  const request = event.request;
  if (!request.url.startsWith(location.origin)) {
    // Skip cross origin requests
    return false;
  }
  event.respondWith(fetch(request));
});

I.e. skip handling any cross origin requests in the SW (including PNA requests) and explicitly send other requests (including the document request) onto the wire using fetch. With this setup the UA will not send any preflight requests for { targetAddressSpace: 'private' } requests, but still send the actual request. If you bypass the SW for the document request or if you skip handling the document request in the SW it will work as expected.

Here's a minimal setup to reproduce: https://www.danielbaulig.de/pna-sw-bug/
Make sure to enable Permission Prompt for Private Network Access experiment in about:flags, since this origin is not part of the origin trial.
Load the page, confirm the prompt with any private host/IP address. In the developer tools network tab you will see that the request to the private host/IP address is sent without a preflight request.

Also note that the request will correctly fail with a mixed-content warning when not in the PNA Permission Prompt experiment.

@DanielBaulig DanielBaulig changed the title Implementation bug with relevance for user security and privacy PNA permission prompt implementation bug with relevance for user security and privacy Jan 28, 2024
@DanielBaulig DanielBaulig changed the title PNA permission prompt implementation bug with relevance for user security and privacy PNA permission prompt implementation bug in Chrome 121 with relevance for user security and privacy Jan 28, 2024
@DanielBaulig
Copy link
Author

I'm a little bit surprised that there does not seem to be any interest in this. It seems like a serious issue that can be exploited by applications in the wild opting into the origin trial.

Since I am assuming that this is an implementation bug and not a bug in the specification (although I am not sure) I've decided to also file a bug against Chromium which might be the better avenue for implementation issues, rather than this WICG issue tracker: https://issues.chromium.org/issues/323583084

I'm mentioning some people here to get some eyes on this. If you guys deem this to not be an issue please let me know and I will shut up about it :)
@johnathan79717 @iVanlIsh

@iVanlIsh
Copy link
Collaborator

Thanks for the report. It is a serious bug indeed. I'm trying to debug it.

@DanielBaulig
Copy link
Author

Thanks for circling back. Let me know if there's anything I can do to help.

@iVanlIsh
Copy link
Collaborator

I tried it on Chrome 121.0.6167.184. It seems to be work as expected. Are you trying it with localhost IP addresses or a private address? localhosts are secure context for mixed content checkers.

@DanielBaulig
Copy link
Author

DanielBaulig commented Feb 14, 2024

Just updated to the latest stable version of Chrome (Version 121.0.6167.184) and it is definitely sending those requests.

I've put together a minimal repro here: https://www.danielbaulig.de/pna-sw-bug/
Make sure to enable the PNA Permission Dialog flag in your browser, since that origin is not opted into the Origin Trial.
Also make sure that the Service Worker is installed and running the specific code (including returning false early for requests going to different origins). If you have "Bypass for network" or prevent the SW from handling the request otherwise, you will not trigger the issue. Also, to your own point, do not try to test this running a web server on localhost / 127.0.0.1 / any other local address space IP address. As you pointed out, that origin is not subject to the exact same limitations and restrictions than a non-local origin. I'm frankly not even sure what exactly the differences are, just make sure to serve the app from a secure origin that is not in the local address space.
Open the developer network tab so you can monitor what is going on from a network perspective.

Once the preconditions are met reload the page. It will present you with an input prompt that you can enter an IP address or hostname in. You could enter a hostname here, but choosing an IP address will avoid any issues with DNS/mDNS getting in the way. Enter any valid private address space IP address. It doesn't really matter if that address exists on the network or not and if it is running an HTTP service or not. Just make sure it's in the private network address space.

Confirm the dialog and watch the network request tab. You will see that the UA has sent a fetch to the destination address. It will be a GET request and not a CORS OPTIONS preflight request, which it should. Depending on if the host exists and if it is running an HTTP server giving a response and depending on the CORS headers in that response what will happen next may be that the request times out, or it fails because of the CORS Same Origin policy or it succeeds providing a response.

In either case, the issue already occurred, which is that a GET fetch request was sent without a permission dialog / OPTIONS preflight request.

Hope this is helpful.

Edit: If you are still struggling with reproducing the issue I can do a screen recording of me performing the exact steps that lead to the issue and share it with you. Let me know if that is something you might find useful.

@iVanlIsh
Copy link
Collaborator

Sorry, I still could not reproduce it. Would you mind sending me a screen recording?

The mixed content check should happens and fails before the request going to service worker which is what happened exactly when I try to reproduce the issue.

@DanielBaulig
Copy link
Author

I'll make a screen recording and share it with you.

With PNA permission prompt enabled the mixed content check gets disabled and replaced with the PNA preflight request though, right? So no mixed content check will happen before the request goes to the SW. It seems to me that whatever then happens in the SW then doesn't trigger the actual PNA preflight/permission dialog.

If you are getting a mixed content check before the request goes to the service worker your setup is likely incorrect. The private network request should not be subject to mixed content policy but instead subject to PNA permission dialog with PNA permission dialog enabled.

@DanielBaulig
Copy link
Author

Here's the screen recording: https://www.youtube.com/watch?v=lvY5E4YfKGQ

What isn't shown in the screen recording is that I had also just reset all page permissions and cleared all page data. I wasn't sure if that would clear any PNA related settings or data, but just wanted to make sure I do my due diligence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants