w3c / webtransport

WebTransport is a web API for flexible data transport
https://w3c.github.io/webtransport/
Other
820 stars 51 forks source link

CSP policies for WebTransport? #59

Open mfoltzgoogle opened 4 years ago

mfoltzgoogle commented 4 years ago

Currently, data exchange capabilities that are exposed to the Web are restricted through CSP connect-src, which restricts which origins can be connected to through WebSockets, XHR, etc.

  1. Will every WebTransport destination have an origin that can be verified by the UA (through Web PKI or some other means)?
  2. If the answer to "1" is yes, will WebTransport use connect-src or some other CSP policy mechanism?
  3. If the answer to "1" is no, how will application authors be able to enforce a WebTransport connection policy in their application?
mfoltzgoogle commented 4 years ago

Possibly related to (or a specific issue in) Issue #13

vasilvv commented 4 years ago

I think this is yet another issue that can be addressed by providing QuicTransport endpoints with URLs associated with it. So if we add URL for #22 and #26, we would probably get CSP support for ~free.

aboba commented 3 years ago

Discussed on December 8, 2020 WebTransport WG meeting. Agreement to support CSP for the Web PKI case. Concerns over impact of fingerprint verification on CSP support.

jan-ivar commented 3 years ago

@vasilvv to write text and reach out to webappsec to discuss some of the more complex cases.

vasilvv commented 3 years ago

So I think the answer for WebPKI-authenticated connections is fairly clear: we will check connect-src for WebTransport connections.

For the connections that are anchored against a custom certificate, I can see a few approaches:

  1. Make this orthogonal to CSP connect-src. One approach would be to add a new header, say, Sec-WebTransport-Allow-Custom-Certificates, that would opt the website into using custom certificates, or somehow encode that into CSP.
  2. Encode the fingerprint within the domain name. An approach I'd gp with is where a domain like example.com with certificate fingerprint 0x1234abcd gets translated into example.com.domain-1234abcd.fpr.arpa (I think @ekr proposed something among those lines a few years ago when I discussed that problem with him).

The first approach has the advantage of being very simple, but less powerful, as it's just an all-or-nothing approach. The second approach lets developers control the specific fingerprints, but it does require us to do more work. Notably, I have no idea what the policies are wrt assigning .arpa domain names, and what are all of the implications.

cc @mikewest since he expressed interest in this topic in the past. cc @martinthomson and @DavidSchinazi as they probably know more about .arpa

martinthomson commented 3 years ago

The discussions on webrtc-src are relevant here: w3c/webappsec-csp#457

I would say that a binary toggle for "custom certificate allowed" is probably easier than otherwise. Reconciling that with the WebRTC control would be ideal. Devising a new means of identifying specific certificates, similar to script-src with nonces, seems like a stretch goal.

You might consider a webtransport-src rule that inherits from connect-src.

jan-ivar commented 3 years ago

Meeting:

martinthomson commented 3 years ago

One addendum: just use a boolean flag ('fp') to turn custom certificate fingerprints on/off rather than devise a system for identifying specific fingerprints (do that later).

annevk commented 3 years ago

As I mentioned in one of the WebRTC threads, I think acting as if "obtaining the connection" failed is preferable as it gives more freedom to where implementations decide to enforce the policy and makes the API contract for developers simpler.

mikewest commented 3 years ago

Seconding @annevk; we started enforcing on fetch() and XHR by throwing in the constructor, and shifted towards failing the connection instead, as it unified behavior between initial requests and redirects. I don't think that specific thing is a problem for web transport, but I do think aligning the behavior between WT on the one hand and fetch() on the other seems like the right way to go.

martinthomson commented 3 years ago

So a new way to reject the ready promise?

annevk commented 3 years ago

Assuming the description at https://w3c.github.io/webtransport/#webtransport-ready is correct, yes. Using the same exception you do now to reject on connection establishment failure. (fetch() uses JavaScript's generic TypeError for all this.)

jan-ivar commented 2 years ago

@yutakahirano With https://github.com/w3c/webtransport/pull/367 merged can this be closed now, or was it left open for a reason?

My understanding of that PR is that we now link to CSP and that the details of how that policy works will be handled there. Is that right?

yutakahirano commented 2 years ago

The interaction between custom certificates hasn't been resolved yet, IIRC.

vasilvv commented 2 years ago

Regarding the issue with custom certificates, I've been trying to figure the exact threat model for this issue. The model I currently have in my head is roughly: if an attacker can inject code into the webpage, and they can do active network attacks, then they can work around CSP policies (such as connect-src 'self') by establishing a connection to an allowed CSP origin but using custom certificate API to bypass the certificate check that would normally stop them. This is a fairly niche attack (due to the combination of those two prerequisites), but it's something we should still probably address.

A simple flag to control this was the approach we've agreed to last time we discussed this during a WG meeting, and I think it should be sufficient. We still need to figure out the placement and syntax for this; as a starting point, I am going to suggest adding a webtransport-no-certificate-hash directive to CSP that has no arguments and that automatically blocks all WebTransport connections that use serverCertificateHash argument. What do people think?

cc @martinthomson @mikewest

DavidSchinazi commented 2 years ago

Alternatively, could we add an HTTP header to the extended CONNECT request that mentions whether custom certificates were configured by the client JavaScript? That way server implementations could be configured by default to abort if that header is present.

martinthomson commented 2 years ago

I'm a fan of a new 'certificate-hash' label for 'connect-src' and friends, which would be off by default and so cascade down naturally (being disabled automatically if CSP rules were in play).

vasilvv commented 2 years ago

I'm a fan of a new 'certificate-hash' label for 'connect-src' and friends, which would be off by default and so cascade down naturally (being disabled automatically if CSP rules were in play).

That would be a good approach, though I am not sure this is backwards-compatible, i.e. if a website sends connect-src certificate-hash to a browser that does not recognize it, would that break the directive?

martinthomson commented 2 years ago

That form of compatibility is fairly simple. Under (my understanding of[^1]) the CSP extension model, new directive values can only be more permissive, so it is safe to ignore unknown values.

The sort of compatibility problem that concerns me is the one where we ship the capability, then attempt to retrofit CSP to it. There, sites will exist that use connect-src (and derivatives) and certificate hashes successfully, so adding a special directive value to connect-src will result in those sites suddenly breaking. This is the problem WebRTC had to deal with; the result being somewhat inelegant.

[^1]: The CSP spec is remarkably obtuse and lacking in basic explanatory text that might make it easy to answer this sort of question, so I'm going on inference.

jan-ivar commented 2 years ago

Meeting:

jan-ivar commented 2 years ago

Meeting:

jan-ivar commented 2 years ago

Meeting:

jan-ivar commented 2 years ago

@vasilvv did you have time to look over the CSP spec? Can we close this now?

nidhijaju commented 8 months ago

Discussed this with @vasilvv offline, and it's not clear if the current state is sufficient or we need to add anything to the CSP spec. Maybe worth discussing at the next meeting.

jan-ivar commented 4 months ago

Meeting:

jan-ivar commented 4 months ago

From https://github.com/w3c/webtransport/issues/59#issuecomment-1056019468 it looked like we were almost home:

Meeting:

  • People who use the custom certificates today in Chrome might be broken if we use connect-src 'certificate-hash'
  • Might be OK if we do it quickly.

@vasilvv do we still think connect-src 'certificate-hash' might work here? Should we not just do that?

jan-ivar commented 2 months ago

Meeting:

jan-ivar commented 1 month ago
  • People who use the custom certificates today in Chrome might be broken if we use connect-src 'certificate-hash'

Based on chrome status it doesn't seem too late to do this.

From my (limited) understanding of CSP keywords, we'd need to define the keyword's interaction with other sources:

Content-Security-Policy: connect-src 'certificate-hash' https://A.com https://B.com

Clearly, this would disallow

new WebTransport("https://C.com"); // C is not A or B

But would it also disallow

new WebTransport("https://C.com", {serverCertificateHashes: [{algorithm: "sha-256", value}]});

?

If there's security value in limiting connects to specific URLs even without Web PKI, then probably yes.

jan-ivar commented 3 weeks ago

Even if we do limit use of serverCertificateHashes to those URLs (A and B), there's no way to limit it just to A (and still allow B with TLS). That would probably require an independent directive instead. Something like:

Content-Security-Policy: webtransport-certificate-hash https://A.com;
                         connect-src https://B.com;