w3ctag / design-reviews

W3C specs and API reviews
Creative Commons Zero v1.0 Universal
332 stars 56 forks source link

Private Network Access (aka CORS-RFC1918) #572

Closed letitz closed 2 years ago

letitz commented 3 years ago

Hi there friendly TAG members,

I'm requesting a TAG review of CORS-RFC1918.

CORS-RFC1918 is a web specification which aims to protect websites accessed over the private network (either on localhost or a private IP address) from malicious cross-origin requests.

Further details:

We'd prefer the TAG provide feedback as (please delete all but the desired option):

🐛 open issues in our GitHub repo for each point of feedback

torgo commented 3 years ago

Hi @mikewest - just picking this up at our "f2f" this week. Has there been any update since the request came through? In particular is there any further info on multi-stakeholder / multi-impleneter feedback?

plinss commented 3 years ago

We discussed this a bit in our VF2F today, and had some concerns about IPv6 addresses. Looking though the repo there seem to be several existing issues already covering our concerns. Linking for visibility/tracking: https://github.com/WICG/cors-rfc1918/issues/6 https://github.com/WICG/cors-rfc1918/issues/28 https://github.com/WICG/cors-rfc1918/issues/36

mikewest commented 3 years ago

Hey @torgo! @letitz is driving this inside Chromium. I'm just pointy-haired overhead at this point.

We have weak signals of interest from both WebKittens (https://bugs.webkit.org/show_bug.cgi?id=218623#c36) and Mozillians (https://github.com/mozilla/standards-positions/issues/143 and https://bugzilla.mozilla.org/show_bug.cgi?id=1481298), but nothing that rises to the level of "support" from the Blink process's perspective.

Still, this feels to me like an important problem, and one that hasn't generated any other proposals in the very-long-time-indeed since we originally wrote it. It's something Chromium is actively working towards (we aim to deprecate non-secure local network access in ~three milestones), and if there's a better direction, it would be excellent to discover it quickly. :)

letitz commented 3 years ago

Hi @plinss, thanks for taking a look!

I believe IPv6-related discussions in the issues you link have been resolved, largely thanks to wicg/private-network-access#30. I've updated the issues you linked in the repo to better reflect the current state of affairs.

Do you have other concerns you would like to discuss?

torgo commented 3 years ago

Bringing this to the attention of @wseltzer, @martinthomson as this could use some scrutiny with regard to W3C / IETF liaison…

annevk commented 3 years ago

(FWIW, I think a lot of this will necessarily have to end up in the WHATWG, but getting review from the IETF would be great.)

martinthomson commented 3 years ago

I apologize for the delay here, but I've started a conversation about this. My read is that this an entirely appropriate application of the addressing architecture and it will likely provide meaningful improvements for services that are inadequately protected by means other than firewalls.

I have a couple of minor concerns with the proposal:

It seems like this could use a structured field, but I realize that the original version of this predates that work by a lot.

I couldn't work this out quickly: does the preflight result in revealing that a server exists at the identified address/name? That is, does this change make service enumeration on private address ranges easier, no different, or harder?

(I agree with Anne that this is almost entirely a Fetch feature and this should probably move to a pull request on that specification.)

martinthomson commented 3 years ago

Apologies for the followup...

Another deliberate exclusion here is that servers that are already in a "private" context can attack each other without engaging the additional consent protections. My understanding is that this exclusion exists for two reasons: 1. because we assume that these services can already talk to each other, and 2. so that enterprise services can "talk" to each other.

Lateral communication is not a guaranteed property of the system. An RFC 1918 address (i.e., IPv4) might not naturally be able to access an IPv6 ULA. Good network-level controls might aim to prevent lateral communication between servers in a network, so that even if clients can talk to any server, servers can only talk to other servers that they need to. These safeguards might exist to limit the ability of a compromised service attacking other services.

The same applies to services running on localhost. The application that maintains that service can probably talk to other services on localhost, but this is not always the case. A browser might be given access to all local ports, but specific applications might be prevented from unfettered communication. Using the browser to circumvent those restrictions might not be something the administrator/user wants.

Acknowledging that these choices are deliberate would be good. FWIW, I don't think that it would hurt to treat loopback to loopback as a "private" request, though the compatibility risk involved with restricting lateral movement within networks probably makes the same constraint harder to apply at the next layer out.

martinthomson commented 3 years ago

To close the loop some. There are some fairly strong negative reactions from people at the IETF. I'll use @hardie's more concise summary as a stepping off point. Read the entire thread in the archive for more context.

annevk commented 3 years ago

I filed https://github.com/WICG/private-network-access/issues/42 on user consent.

The preflight shouldn't result in new information leakage. I don't think it changes anything as far as service enumeration goes.

There is an open issue on requiring the preflight whenever you go across origins on non-public addresses, but it would likely result in significant breakage so that's not part of the initial plan.

It seems a lot of the remaining concerns are about somehow conveying the limitations of this approach clearly, though it's not clear to me if that mainly pertains to prose or also naming. (And if the latter, what better names would be.)

letitz commented 3 years ago

Thanks Martin for the review. I apologize in turn for taking a while to respond.

it will likely provide meaningful improvements for services that are inadequately protected by means other than firewalls.

I would go further and add that the intent is to provide meaningful improvements for services that are protected by firewalls. Indeed, an IoT device might think it's well protected if it sits behind a firewall, but still receive HTTP requests crafted by evil.com.

Regarding user consent, as I just replied on WICG/private-network-access#42, I agree. I think we can downgrade that recommendation to MAY rather than SHOULD.

This proposal is no substitute for services providing encryption and proper access controls. This proposal does not protect adequately against true cross-protocol attacks that use either unencrypted HTTP or attacker-controlled components of TLS handshakes to attack poorly-protected servers from the vantage point of a client (we have a port number blocklist that is designed to help, but we know that too is not perfect).

Very true. Filed https://github.com/WICG/private-network-access/issues/43 to mention this in the spec.

this proposal cannot protect services that are reachable from globally reachable addresses. If a firewall protects services that can be reached with a globally reachable address, even if that service is not genuinely globally reachable due to the firewall, then the consent check will not be engaged and the service might be vulnerable to attack.

Also true. Filed https://github.com/WICG/private-network-access/issues/44 for this.

It seems like this could use a structured field, but I realize that the original version of this predates that work by a lot.

Good point. We have not yet started implementing the preflights, so we might as well modernize the spec while it's cheap to do so. Filed https://github.com/WICG/private-network-access/issues/45 for this.

I couldn't work this out quickly: does the preflight result in revealing that a server exists at the identified address/name? That is, does this change make service enumeration on private address ranges easier, no different, or harder?

The preflight shouldn't result in new information leakage. I don't think it changes anything as far as service enumeration goes.

+1. Timing attacks are already possible that reveal which IP adresses exist on the private network. The preflight would not change that - it offers no protection, and neither does it leak additional information. See also https://github.com/WICG/private-network-access/issues/41.

Another deliberate exclusion here is that servers that are already in a "private" context can attack each other without engaging the additional consent protections. My understanding is that this exclusion exists for two reasons: 1. because we assume that these services can already talk to each other, and 2. so that enterprise services can "talk" to each other.

There is an open issue on requiring the preflight whenever you go across origins on non-public addresses, but it would likely result in significant breakage so that's not part of the initial plan.

Indeed, see https://github.com/WICG/private-network-access/issues/39.

Acknowledging that these choices are deliberate would be good.

Agreed. This is mentioned briefly as ISSUE 2 in https://wicg.github.io/private-network-access/#integration-fetch. It would be good to harmonize that section with https://wicg.github.io/private-network-access/#private-network-request-heading. Filed https://github.com/WICG/private-network-access/issues/46.

FWIW, I don't think that it would hurt to treat loopback to loopback as a "private" request, though the compatibility risk involved with restricting lateral movement within networks probably makes the same constraint harder to apply at the next layer out.

I'm not sure about the compatibility risk of breaking loopback to loopback. Since this is a strictly additive change, I would be in favor of deferring it along with https://github.com/WICG/private-network-access/issues/39.

letitz commented 3 years ago

As for the IETF comments, I see a few main points beyond what Martin summarized above. Here is my interpretation of these, and responses:

1. The specification is misleading, purporting to fix things that it cannot entirely address.

This is a fair point. The spec can and should do a better job of explaining the limitations of this approach. Filed https://github.com/WICG/private-network-access/issues/47.

2. IP address bits are insufficient to correctly understand network topology.

Entirely agreed. This is a practical, non-theoretically-satisfying approach that can meaningfully improve on the status quo (no protections whatsoever) with minimal breakage. This should be clarified, per https://github.com/WICG/private-network-access/issues/47.

2.1. NATs confuse private and public IP addresses.

I don't fully understand the point being made here. Some private IP addresses are used for "globally-reachable" endpoints and NATed. I believe this entails that IP addresses behind the NAT will believe that they belong to the same private network, when they could e.g. belong to different ISP subscribers.

I can see two consequences:

b) looks very unlikely to me. Either the website makes a request to a hostname that requires a DNS lookup, in which case the DNS would have to return the non-translated address (possible, but a bit weird), or it would have to target the non-translated address, in which case how could it know the address without itself being behind the NAT?

2.2. Treating all private IP addresses as belonging to the same private address space is incorrect. Many private IPs reside on distinct networks and cannot reach each other.

Correct. This is still an improvement on the status quo, where even public IP addresses can talk to private IP addresses. This should be clarified per https://github.com/WICG/private-network-access/issues/47.

2.3. Large networks (e.g. corporate) make use of globally-reachable addresses for their private networks. These are left unprotected. Ditto for IPv6 addresses behind firewalls.

I have been thinking that a mechanism for administrators to override the address space of certain subnets would be very useful. Filed https://github.com/WICG/private-network-access/issues/48 for this. This allows network administrators to opt into the protections afforded by this spec. It does not address the home IPv6 angle though.

2.4. Some network operators make use of unrouted IP addresses for extra private IPs.

IIUC these should not be considered "globally-reachable", thus they should be considered private.

3. The SOHO pharming link is broken.

Filed https://github.com/WICG/private-network-access/issues/49 for this.

5. Having "browsers decide" (unilaterally) what is OK and not is misguided.

This seems to stem from a misunderstanding of the CORS part of the specification. The browser does ask the target endpoint whether or not to allow the connection.

Beyond that, it is true that browsers are making decisions regarding what they allow or do not allow. I do not see a qualitative distinction between this and say mixed content. User agents have a duty to protect their least-technically-savvy users.

6. What happens to old devices that cannot update?

This is touched upon in the specification: the expected failure mode is that they do not reply to the OPTIONS request and thus are protected.

torgo commented 3 years ago

Hi @letitz - OK we are just looking at this again in our virtual F2F. It feels like you are engaging with the feedback raised in IETF. The TAG is generally supportive of this work and we understand and agree with the user need as documented. There still seems to be some work to do with the IETF feedback. However we're going to close this for now here and we suggest that further discussion should happen in the spec's repo. Please re-open this issue when you have a new version to review and we can take another look.

letitz commented 3 years ago

Hi @torgo, I believe all of Martin's concerns have been resolved. I rewrote the Fetch integration section to be much less handwavy too. All in all, the spec is ready for another look.

letitz commented 3 years ago

Hello again @torgo! I cannot seem to re-open this issue. Maybe I do not have the required permissions? In any case, this can be re-opened as per the comment above.

torgo commented 3 years ago

Hi @letitz We have reopened and are taking a look. Could you give a little more detail on what's changed e.g. in the Fetch integration section? That would help us re-review. Thanks!

letitz commented 3 years ago

Hi @torgo! Sorry for the late response, I was in and out of the office for a bit and dropped this.

A bunch of things have changed - all in all I'd say at least half of the spec was rewritten. More specifically:

The Fetch integration has been re-written to refer to the latest Fetch spec version (as opposed to a years-old version). It is much closer to a real patch, with concrete definitions, less handwavy overall.

The IP address space classification has been re-worked to be simpler and drop the dependency on the IANA special address registry, per suggestions by network experts / the IETF.

The secure context restriction is now specified separately from the CORS preflights, allowing a more straightforward mapping of Chromium changes to parts of the spec (I'm trying to ship the secure context restriction for subresources).

The HTML integration section has been dramatically simplified by relying on the policy container work by @antosart to implement inheritance correctly.

Finally, discussions of both proxy and cache handling have been significantly expanded to explain the risks and tradeoffs involved.

HTH!

torgo commented 3 years ago

Hi @letitz - we're picking this up today and thanks for the info on what to look for.

ylafon commented 3 years ago

We discussed this again in our Virtual F2F, and had questions about legacy devices. As one goal is to ensure that you don't attack devices, legacy devices that can't be updated comes to mind, link printers. Most of those devices are usually advertised on the local network, so the UA might be able to figure them out and allowing access like a "paired" device (to avoid completely blocking them out).

Another issue is, should the local network be only the ip/netmask range and not the list of all the private ranges?

letitz commented 3 years ago

We discussed this again in our Virtual F2F, and had questions about legacy devices. As one goal is to ensure that you don't attack devices, legacy devices that can't be updated comes to mind, link printers. Most of those devices are usually advertised on the local network, so the UA might be able to figure them out and allowing access like a "paired" device (to avoid completely blocking them out).

The goal is not to block any and all accesses to local network devices, but rather to prevent CSRF attacks on them. As such, only requests initiated by more-public websites will be subject to new restrictions.

If such a device offers its own UI on http://printer.local, and the user navigates there by typing it in the URL bar, then no restrictions are applied and things will work as before.

As for pairing, that's an interesting question. Without using HTTPS to cryptographically authenticate the target device, granting access permissions seems to open the door to confused deputy issues. Are you suggesting "pairing" ceremonies between origins and devices advertising themselves using mDNS?

Another issue is, should the local network be only the ip/netmask range and not the list of all the private ranges?

Currently, all IP ranges specified in RFC 1918 are considered private, as well as a few others. See this algorithm in the spec. An earlier version of this spec proposed to rely on the IANA special-purpose address to define address spaces, but that was discouraged by network experts upon consultation: see https://github.com/WICG/private-network-access/issues/50.

Edit: Oh, I think I misunderstood your point. You mean to suggest that only the current subnet be considered private? That makes some sense in terms of protecting the devices around the user. I stand by the belief that considering all private ranges as private makes more sense, because a public website initiating a request to 10.0.0.1 would usually not be able to reach the same host using that address. In other words, as the spec currently states: "[the private address space] contains addresses that have meaning only within the current network. In other words, addresses whose target differs based on network position."

ylafon commented 3 years ago

Hi @letitz

Yes, it is quite clear that the goal is to prevent CSRF attacks, but for example, being able to access a device on your local network from outside has its value, be it a printer, a music player or a cloud-based configuration manager for some of your local devices. In the first case, you can't really expect to upgrade the firmware on your printer, while on the second case it is trivial to do so to support a more secure way of allowing this kind of interaction.

This is the reason why it would be good for some services to see them not as services, but as attached pseudo-devices (the printer case).

On the second point, I think there is a difference between the local network and the private networks you can reach, like corporate private networks. The pseudo-device use case makes sense only for local networks, not for corporate private networks, for example.

letitz commented 3 years ago

This is the reason why it would be good for some services to see them not as services, but as attached pseudo-devices (the printer case).

Making sure I understand your concern correctly:

  1. Certain devices will not be able to update and support CORS preflights, for example old printers
  2. There should be a way for websites to request access to such devices that bypasses PNA restrictions

If I've understood correctly, then I can certainly see your point. I have two reservations, however:

  1. This mechanism would significantly reduce the incentive for devices to implement PNA proper. In other words, it seems advantageous for device maintainers (and disadvantageous for user security) to classify all services as pseudo-devices.
  2. It begs the question: how do you identify a pseudo-device? IP address alone works to an extent, but is hardly fool-proof. mDNS names are not authenticated either, though one could argue that on the private network they should be relatively stable.

On the second point, I think there is a difference between the local network and the private networks you can reach, like corporate private networks. The pseudo-device use case makes sense only for local networks, not for corporate private networks, for example.

Oh, so you propose allowing the pseudo-device attachment only work within the currently subnet(s)?

ylafon commented 3 years ago

Making sure I understand your concern correctly:

  1. Certain devices will not be able to update and support CORS preflights, for example old printers
  2. There should be a way for websites to request access to such devices that bypasses PNA restrictions

Well, not really bypass restrictions, as the goal would not to let them be available through http, but as an attached device.

If I've understood correctly, then I can certainly see your point. I have two reservations, however:

  1. This mechanism would significantly reduce the incentive for devices to implement PNA proper. In other words, it seems advantageous for device maintainers (and disadvantageous for user security) to classify all services as pseudo-devices.

I don't think so, as not all services can be seen as a pseudo device, router configuration is definitely not in that range. I think more about devices sitting on the local network where the function can be identified easily.

  1. It begs the question: how do you identify a pseudo-device? IP address alone works to an extent, but is hardly fool-proof. mDNS names are not authenticated either, though one could argue that on the private network they should be relatively stable.

mDNS is probably the most reliable way to identify an ipp or roap device, for example, but it is just a possibility.

On the second point, I think there is a difference between the local network and the private networks you can reach, like corporate private networks. The pseudo-device use case makes sense only for local networks, not for corporate private networks, for example.

Oh, so you propose allowing the pseudo-device attachment only work within the currently subnet(s)?

Yes, on remote private network, you can imagine that gateways to implement PNA would be in place to access devices that can't be directly upgraded.

letitz commented 2 years ago

Making sure I understand your concern correctly:

  1. Certain devices will not be able to update and support CORS preflights, for example old printers
  2. There should be a way for websites to request access to such devices that bypasses PNA restrictions

Well, not really bypass restrictions, as the goal would not to let them be available through http, but as an attached device.

Do you propose to introduce a new API for loading websites that does not use http, then? Or a new scheme perhaps? Though that would not prevent CSRF, so I think I am missing your point. Could you explain how you envision a user agent would interact with a pseudo-device?

If I've understood correctly, then I can certainly see your point. I have two reservations, however:

  1. This mechanism would significantly reduce the incentive for devices to implement PNA proper. In other words, it seems advantageous for device maintainers (and disadvantageous for user security) to classify all services as pseudo-devices.

I don't think so, as not all services can be seen as a pseudo device, router configuration is definitely not in that range. I think more about devices sitting on the local network where the function can be identified easily.

Who makes that call, and how is it made? I think this is a crucial question with such an approach.

Either the user agent has some list of acceptable pseudo-devices, or the target service must be trusted to self-identify, in which case we are back to solution relatively similar to the current proposal.

In the former case, it seems that the only recourse we have is to ask either the host OS or the user for help determining what are acceptable pseudo-devices to communicate with. I have shied away from asking users for input on the theory that most will be unable to make an educated decision on the risks involved with allowing a random website to probe at a private network device. As a defense-in-depth measure, I am not opposed to it. However, I believe relying on user consent alone would significantly weaken the protections afforded by the preflight protocol envisioned in the current spec.

  1. It begs the question: how do you identify a pseudo-device? IP address alone works to an extent, but is hardly fool-proof. mDNS names are not authenticated either, though one could argue that on the private network they should be relatively stable.

mDNS is probably the most reliable way to identify an ipp or roap device, for example, but it is just a possibility.

On the second point, I think there is a difference between the local network and the private networks you can reach, like corporate private networks. The pseudo-device use case makes sense only for local networks, not for corporate private networks, for example.

Oh, so you propose allowing the pseudo-device attachment only work within the currently subnet(s)?

Yes, on remote private network, you can imagine that gateways to implement PNA would be in place to access devices that can't be directly upgraded.

That makes sense.

ylafon commented 2 years ago

Making sure I understand your concern correctly:

  1. Certain devices will not be able to update and support CORS preflights, for example old printers
  2. There should be a way for websites to request access to such devices that bypasses PNA restrictions

Well, not really bypass restrictions, as the goal would not to let them be available through http, but as an attached device.

Do you propose to introduce a new API for loading websites that does not use http, then? Or a new scheme perhaps? Though that would not prevent CSRF, so I think I am missing your point. Could you explain how you envision a user agent would interact with a pseudo-device?

Not really, my point was to make it seen (if allowed) as a peripheral directly attached to the computer, with the browser deciding which device can be seen or not. That would solve the use case of legacy devices like printers, scanners, cameras, etc... But how it can be done, or even would it be the best solution for enabling those legacy devices is out of scope of this review.

If I've understood correctly, then I can certainly see your point. I have two reservations, however:

  1. This mechanism would significantly reduce the incentive for devices to implement PNA proper. In other words, it seems advantageous for device maintainers (and disadvantageous for user security) to classify all services as pseudo-devices.

I don't think so, as not all services can be seen as a pseudo device, router configuration is definitely not in that range. I think more about devices sitting on the local network where the function can be identified easily.

Who makes that call, and how is it made? I think this is a crucial question with such an approach.

Either the user agent has some list of acceptable pseudo-devices, or the target service must be trusted to self-identify, in which case we are back to solution relatively similar to the current proposal.

In the former case, it seems that the only recourse we have is to ask either the host OS or the user for help determining what are acceptable pseudo-devices to communicate with. I have shied away from asking users for input on the theory that most will be unable to make an educated decision on the risks involved with allowing a random website to probe at a private network device. As a defense-in-depth measure, I am not opposed to it. However, I believe relying on user consent alone would significantly weaken the protections afforded by the preflight protocol envisioned in the current spec.

Decisions in that case shouldn't be on the user, to avoid permission fatigue.

  1. It begs the question: how do you identify a pseudo-device? IP address alone works to an extent, but is hardly fool-proof. mDNS names are not authenticated either, though one could argue that on the private network they should be relatively stable.

mDNS is probably the most reliable way to identify an ipp or roap device, for example, but it is just a possibility.

On the second point, I think there is a difference between the local network and the private networks you can reach, like corporate private networks. The pseudo-device use case makes sense only for local networks, not for corporate private networks, for example.

Oh, so you propose allowing the pseudo-device attachment only work within the currently subnet(s)?

Yes, on remote private network, you can imagine that gateways to implement PNA would be in place to access devices that can't be directly upgraded.

That makes sense.

We discussed this again during our F2F, and decided that it looks good enough to close it. Thanks!

johnathan79717 commented 1 year ago

FYI that we're planning to allow same-origin fetches to potentially-trustworthy origins https://github.com/WICG/local-network-access/issues/89