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

Consider removing serverCertificateHashes #623

Open
annevk opened this issue Dec 3, 2024 · 23 comments
Open

Consider removing serverCertificateHashes #623

annevk opened this issue Dec 3, 2024 · 23 comments
Labels
Discuss at next meeting Flags an issue to be discussed at the next WG working

Comments

@annevk
Copy link
Member

annevk commented Dec 3, 2024

Without more restrictions this feature could lead to the same kind of problem plaguing Web Push, where messages are not end-to-end encrypted because it's easier to let middleware worry about the complexity of encryption and dealing with the Web Browser Endpoint in general.

I also heard that the main motivation for this feature is local development and testing, which does not meet the high bar we have for web platform features.

As things stand today WebKit does not intend to implement this.

@vasilvv
Copy link
Contributor

vasilvv commented Dec 3, 2024

Without more restrictions this feature could lead to the same kind of problem plaguing Web Push, where messages are not end-to-end encrypted because it's easier to let middleware worry about the complexity of encryption and dealing with the Web Browser Endpoint in general.

I do not understand this comparison. What does Web Push or middleware has to do with serverCertificateHashes?

I also heard that the main motivation for this feature is local development and testing, which does not meet the high bar we have for web platform features.

This is not correct; the motivation for this feature is to provide the ability to connect to endpoints that cannot have a publicly trusted certificate, in order to have feature parity with WebRTC in that regard. The original reasoning for adding it is documented in #18. Since that discussion happened, more motivation came from scenarios like WICG/private-network-access#23.

@annevk
Copy link
Member Author

annevk commented Dec 3, 2024

I do not understand this comparison. What does Web Push or middleware has to do with serverCertificateHashes?

The risk that people will just use a shared private certificate across a range of devices just to get this to work without actually caring much about end user security.

And while there is definitely a need for some kind of HTTPS for local networks, we should not solve it on a per-API basis.

@youennf
Copy link

youennf commented Dec 3, 2024

in order to have feature parity with WebRTC in that regard

WebRTC is peer-to-peer hence the current solution for WebRTC.
WebTransport being client/server, it seems more consistent to stick with what other client/server networking stacks like HTTP or WebSocket are doing.

@vasilvv
Copy link
Contributor

vasilvv commented Dec 3, 2024

The risk that people will just use a shared private certificate across a range of devices just to get this to work without actually caring much about end user security.

We have discussed this issue previously in #349; this resulted in an expiry requirement being added, as documented in https://w3c.github.io/webtransport/#certificate-hashes.

@annevk
Copy link
Member Author

annevk commented Dec 3, 2024

I don't see how that addresses the concern. You can generate fresh certificates with a shared private key quite easily, but it's not actually secure.

@vasilvv
Copy link
Contributor

vasilvv commented Dec 3, 2024

You can generate fresh certificates with a shared private key quite easily, but it's not actually secure.

I don't believe this is in any way different from regular Web PKI certificates.

@wilaw wilaw added the Discuss at next meeting Flags an issue to be discussed at the next WG working label Dec 3, 2024
@jan-ivar
Copy link
Member

jan-ivar commented Dec 4, 2024

Meeting:

@annevk
Copy link
Member Author

annevk commented Dec 4, 2024

@vasilvv regular certificates have all kinds of safeguards, including being able to distrust the root if practices like this were to be discovered.

@vasilvv
Copy link
Contributor

vasilvv commented Dec 4, 2024

As far as I am aware, there isn't anything in CA/B BR that requires CAs to check for private key reuse; furthermore, as far as I am aware, reusing private keys is not uncommon in practice.

@martenrichter
Copy link

Just a few thoughts: I use the hashes for:
a) Development, as webtransport has no HTTP. I was not able to set up a development setup without it.
b) For VMs rented from cloud providers. Without this mechanism, one must at least integrate them into a DNS domain for let's encrypt to work. Or set up some automated CA issuer. All this requires a much more infrastructure. (Currently I have to do both because of the websocket fallback).

Regarding reusing certificates:
c.) Yes, people do stupid things, but it would always be bound to the JS code of a particular website. So, if this is compromised, everything is already lost.
d.) One may decide that the IP (for the VM use case) or hostname is set on the CN field and is checked (in the moment 0.0.0.0) and forbid wildcards. In this way, mechanisms are in place to generate certificates for each client individually.

Support in Firefox:
e) In light of this discussion, did Mozilla break serverCertificateHashes intentionally (It requires a root CA in the moment):
https://bugzilla.mozilla.org/show_bug.cgi?id=1934402
f) If no, does it make sense to patch it?
g) Would it make sense to invest time to provide time for a wpt test to prevent such breakage? Or may it happen fast that the feature is removed?

Of course, I would prefer that Webkit support the hashes. But for a web app it may also be an option to recommend other browsers if European DMA results in Gecko and Blink appearing on iOS etc.

@martenrichter
Copy link

Regarding e-g) I have made it anyway: https://phabricator.services.mozilla.com/D231479 .

@martinthomson
Copy link
Member

messages are not end-to-end encrypted

I want to address this, because it is a misconception about this feature.

Consider the two cases where a site, "https://some.example" say, initiates a WebTransport connection:

  1. The site specifies a domain name: "https://example.com".
  2. The site specifies a certificate hash (some long hex string).

In neither case does the identity of the WebTransport host come from something that the user specifies. The root of trust is the site.

In both cases, an attack on the site that results in providing the wrong server identity causes the connection to be vulnerable to interception.

The only difference that I've been able to identify is that the identity of the server in the first case will be logged in a CT log somewhere.

The risk that people will just use a shared private certificate across a range of devices just to get this to work

The identified remedy is only capable of making the API a modest amount harder to use. It doesn't change the security posture meaningfully. Servers like Caddy or tools like mkcert largely eliminate those differences. Of course, the use of the WebPKI tends to lead to people sharing the same private key across a range of devices as well, so it's a bit meaningless.

This feature exists in support of rapid deployment, which includes development scenarios. While I'm somewhat ambivalent about its general utility in a world that includes widespread ACME deployment, I don't think that there's a meaningful security argument for its removal.

@vasilvv
Copy link
Contributor

vasilvv commented Dec 10, 2024

This feature exists in support of rapid deployment, which includes development scenarios. While I'm somewhat ambivalent about its general utility in a world that includes widespread ACME deployment, I don't think that there's a meaningful security argument for its removal.

I feel like local network access use cases are not really addressed by ACME, since the server in question would normally not be accessible by a public CA. Right now, I'm aware of four options available to web developers that need to do something like that:

  1. Get a public CA to issue a certificate to a name that resolves to a private IP, and ship that certificate to the device in question (does not work consistently due to DNS rebinding protection, though I heard there are some ways around that that).
  2. Use WebRTC.
  3. Use WebTransport with serverCertificateHashes.
  4. Use plain HTTP (potentially, if the user agent supports the targetAddressSpace option, that could be limited to subresources only).
  5. Wait until the new API that solves this specific problem materializes (note that this does not count as an option).

Out of those four options, only 2 and 4 work consistently in all web browsers. 2 has proven sufficiently unpalatable to web developers that they have been willing to settle for 4; this situation does not appear to be desirable state for the ecosystem. I believe that 3 could be a sufficient improvement over 2 (in terms of both developer experience, and safeguards against misuse) that it might steer developers away from 4.

And while there is definitely a need for some kind of HTTPS for local networks, we should not solve it on a per-API basis.

Solving this problem for all forms of HTTP requests in general seems to me like boiling the ocean, mostly due to challenges unique to HTTP (caching, top level navigation, cookies, etc). Solving this on per-API basis is more like boiling a water in a kettle, in the sense that we do know how to do that, and there are at least two implemented APIs (one of which is shipped in every major browser engine) that already do that.

@annevk
Copy link
Member Author

annevk commented Dec 10, 2024

But for a web app it may also be an option to recommend other browsers if European DMA results in Gecko and Blink appearing on iOS etc.

This does not seem like acceptable discourse.

@martenrichter
Copy link

But for a web app it may also be an option to recommend other browsers if European DMA results in Gecko and Blink appearing on iOS etc.

This does not seem like acceptable discourse.

Why? It is not insulting, but European legislation about market regulation. It is my reasoning for a small open-source project with no capacity for developing fallbacks for the browsers that do not have newer apis for supporting some critical features (I polyfil for some, but... e.g. webtransport over websocket polyfil, and I have also wrote patches for some browsers). I recommend using the browser that supports the newer features. Only on ios, there is lack of competition, and I would like to support these devices as well fully without much extra work, the option of a switch of browser engine would solve this problem, of course I would prefer to have features on all three engines.... as I am solution oriented, I accept any solution. And serverCertificateHashes is a feature, that I believe is secure and easy to deploy and this ideal for smaller projects.

@mozfreddyb
Copy link

@martenrichter Your point is off-topic for this conversation. Let's focus on the technical merits of the proposal and the pros & cons of using WebTransport and its alternatives.

@jan-ivar
Copy link
Member

jan-ivar commented Dec 17, 2024

Meeting:

@jan-ivar
Copy link
Member

Meeting:

  • What are production use cases outside of development debugging?
  • Talk to device on local network, can't get publicly trusted cert.
  • If the device has some sort of other trust arrangement with a server that does have a cert, could it just issue a cert?
  • A lot of routers will disallow you to DNS to the server you want (?)
  • Martin: not seeing a security issue here
  • Number of certificates needed might be high
  • We lose some of the transparency PKI would provide
  • We think this is not opening a security hole because (1) if it's there it's also in WebRTC, and (2) the abuses discussed in this issue are generally also possible with PKI (how is an ephemeral certificate with a real name different?)
  • One difference might be, with a real cert, if we discover people doing iffy things with it, we can revoke it
  • For parity with WebRTC, in the connect to local device use case, transparency might not be desired, and be less private
  • Pit this against the ability to revoke certs from these people against their privacy?
  • Iffy things: ship a device to lots of people, just take a particular key pair, generate a cert, bake it in the device and never update it. Mitigated by existing expiry date
  • Is this worse than with PKI wrt people being able to reuse keys?

@kixelated
Copy link

kixelated commented Jan 29, 2025

I currently use serverCertificateHashes but only because Chrome didn't seem to work with mkcert (HTTPS worked but not WebTransport). I would be okay with removing support once that implementation detail has been fixed. A few thoughts:

  1. WebRTC needs certificate hashes due to its peer-to-peer design. Peers cannot use DNS nor system signed roots to validate other peers. This is not the case with WebTransport (or HTTPS or WebSockets) given the client-to-server design. Copying HTTPS makes sense.

  2. Certs accepted via serverCertificateHashes are valid for 2 weeks at most. Any long-running server has to figure out a certificate rotation (and revocation?) scheme and it has to be via a secure mechanism otherwise you're vulnerable to MitM. Using HTTPS to fetch cert hashes is not really an option as that requires system roots, defeating the point of using serverCertificateHashes in the first place.

  3. I agree that serverCertificateHashes is not a security vulnerability when used correctly. However, the ephemeral nature of the certs encourages custom and insecure methods of procuring the cert hashes. For example, I'm currently using HTTP to insecurely fetch the certificate hash (fortunately only over localhost). But maybe some developer will get clever and procedurally generate private certificates and their corresponding hash...

  4. Removing the 2 week expiration would allow baking public keys into binaries, for better or for worse. Revocation would not be supported but the same can be said about a self-signed root CA. It might be useful for local networks or applications with secure upgrade paths.

  5. TLS is definitely annoying for local development. Back when I used mkcert for local development, I would often get bug reports when users tried to run clients and servers on different hosts or in docker. It's not obvious that you have to run mkcert on the client (uses a self-signed root) and then transfer the resulting cert to the server. This also only works for a single client host. I spent most of my time trying to explain how certificates work, not how WebTransport works.

The current approach feels like a work-around and not a solution. I don't really care either way, with maybe a slight preference for keeping serverCertificateHashes to make local development easier (5).

@marten-seemann
Copy link

marten-seemann commented Jan 29, 2025

libp2p uses serverCertificateHashes. At my previous job, I wrote a detailed blog post about this: https://blog.libp2p.io/2022-12-19-libp2p-webtransport/

Removing serverCertificateHashes would break this use case, and make WebTransport a lot less useful for the p2p (or more specific: the browser to full node) use case.

@vasilvv
Copy link
Contributor

vasilvv commented Jan 29, 2025

I currently use serverCertificateHashes but only because Chrome didn't seem to work with mkcert (HTTPS worked but not WebTransport).

Chrome works with mkcert as long as you have dev mode in chrome://flags enabled. That said, making local development easier was never the goal for serverCertificateHashes (the main target was supporting ephemeral VMs and local network connections).

@martenrichter
Copy link

  • A lot of routers will disallow you to DNS to the server you want (?)

If it is a VM from a cloud provider, you can just use the DNS name assigned from the cloud. At least, this is the way I have it in my current installation. (Open Telekom Cloud). So this is not an issue. The bigger problem is that UDP is blocked in a lot of networks(university) and I have to fall back to websocket, but this is another story.

  • If the device has some sort of other trust arrangement with a server that does have a cert, could it just issue a cert?
    For my audio video routers, they share a secret with a main controlling server, generate a JSON web token, deposit the hash and DNS name at the server, generate the certificate themselves, and also automatically rotate the certificate. (It is all on GitHub.) It is very stable; I have not had to fix anything for over a year now. But the same is true for the Let's Encrypt certificate I need for WebSockets.
  • One difference might be, with a real cert, if we discover people doing iffy things with it, we can revoke it
    But in order to ramp up a WebTransport connection, one has to be in a secure context, so one would revoke this certificate instead, or have a list of revoked hashes?
  • Iffy things: ship a device to lots of people, just take a particular key pair, generate a cert, bake it in the device and never update it. Mitigated by existing expiry date

Only a device might still bake a private key into the device and generate certificates dynamically.

Chrome works with mkcert as long as you have dev mode in chrome://flags enabled. That said, making local development easier was never the goal for serverCertificateHashes (the main target was supporting ephemeral VMs and local network connections).

Okay, interesting. Actually, when I started developing web transport code, I never got it working with local certificates and Chrome. So servercerticateHashes came to the rescue. (After spending days trying it, where probably a lot of people would use WebSockets and WebRTC out of frustration).
If you start setting up a dev environment, it is a big hurdle with TLS for local development.
Here, it would be good to have something like a how-to, which I may, for example, include in the readme of my node.js package. And maybe others providing similar packages,

Besides, I think a very important point against the stupid use of serverCertificateHashes is education.
Providing example codes and best practices in articles can increase the security of this feature. There is not much material out there, and I think the first good article (I do not mean the spec; the style is a bit terse) is probably getting copied a lot by humans and AI.
I have at least open source code for certificate generation available for node.js (tests of the node package) and python (pull request against wpt tests infrastructure pending initially on Firefox and now transferred by jgraham to github).

@kixelated
Copy link

kixelated commented Jan 29, 2025

I currently use serverCertificateHashes but only because Chrome didn't seem to work with mkcert (HTTPS worked but not WebTransport).

Chrome works with mkcert as long as you have dev mode in chrome://flags enabled. That said, making local development easier was never the goal for serverCertificateHashes (the main target was supporting ephemeral VMs and local network connections).

Let me get this straight. chrome://flags WebTransport Developer Mode reads:

When enabled, removes the requirement that all certificates used for WebTransport over HTTP/3 are issued by a known certificate root.

Does that:

  1. Use system root CAs instead of the Chrome built-in root CAs?
  2. or disable TLS certificate validation entirely? (a literal interpretation)
  3. or something else?

I think it's (1) based on what you're saying. mkcert installs a system root which Chrome happily accepts for HTTPS traffic but not WebTransport (without the flag). VPNs often install system roots to access internal domains, but that wouldn't work without Developer Mode either?

But if it's (2) then oh no.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Discuss at next meeting Flags an issue to be discussed at the next WG working
Projects
None yet
Development

No branches or pull requests

10 participants