EFForg / webrequest-tlsinfo-api

A proposed addition to the Web Extensions API for providing TLS and X.509 information to addons
15 stars 4 forks source link

Feedback on proposal #11

Open april opened 7 years ago

april commented 7 years ago

I can always open up additional issues on the matter, but I have a vested personal interest in this because I would like to use this for extensions that I may write. This is my personal opinion, not necessarily the opinion of Mozilla's NSS/Content Security team.

We propose that a limited set of TLS connection state information be presented in a new object as part of the onCompleted request callback. Providing this information only on the completion of a request would prevent extensions from attempting to meddle with the browsers internal validation engine and would simply provide a window into the outcome of the validation procedures. In cases where the connection fails to complete, such as when Chrome shows validity warning interstitials, the onCompleted event is never actually fired preventing extensions from attempting to subvert various invalidity states.

I'm not entirely sure how I feel about making this information available only in onCompleted. What there was an extension that wanted to block connections made with TLS 1.1, with XYZ certificate authorities, or without forward secrecy? These connections are perfectly valid as far as the browser is concerned, but I can certainly see use cases where a webextension might want to use webRequestBlocking and have more strict reasons to reject a connection other than what the browser considers valid.

Alternatively, they might want to strip/modify session information (i.e. cookies) in onBeforeSendHeaders if it's chained up to a locally installed cert, like a work proxy.

Some of these use cases have better ways to do this in some browsers (such as modifying the acceptable cipher list inside about:config), but not all of them are possible in all browsers that do and/or will support this feature of webextensions.

Both built and sent chain are useful for knowing which path the validation engine considers canonical and for knowing if the server is sending any superfluous certificates in the chain for both third-party telemetry gathering and PageSpeed/SSL Labs style extensions. No further processing needs to be done beyond providing the raw DER as these can be trivially parsed by extensions and third-party services.

While I do think the raw DER should be provided to extensions, I think "trivially parsed" is a bit of a stretch. Most JavaScript ASN.1 parsers are thousands of lines and are far from trivial and would need to get through code review upon submission. Maybe having DER-only is the best solution, but having to parse DER to get the commonName from a certificate seems a bit painful. Browsers have already parsed the certs, so I think it would be better if we could instead returns certs as a JavaScript objects (or JSON), if possible.

Here is what the Mozilla TLS Observatory returns for my current website's certificate: https://tls-observatory.services.mozilla.com/api/v1/certificate?id=13249077

Obviously some of that is TLS Observatory specific, and there are some things that could be more JavaScripty -- for example, validity -> notAfter could return a Date() instead of a string, but I think this is for more usable and wouldn't require every extension to come bundled with their own ASN.1 parser. Simply having to grab tlsInfo.builtChain[0].commonName would be real nice.

tlsVersion: string (optional)

I think this should return the float corresponding to the TLS version (aka 3.2) instead of a string that might need to be parsed. It may even be better to consolidate Protocol and TLS Version into a single protocol: [enum of TLS or QUIC, version], since QUIC also has versioning and then we wouldn't need a specifically named tlsVersion.

chainValid: bool

Maybe just valid? Not sure if that's right or not.

Does exposing information about the sent chain create a privacy risk when it may expose enterprise level MITMs which may be personally (or organizationally) identifying?

This information has always been available in traditional Firefox plugins without any issue and there are certainly ways of detecting a MitM regardless, for example, does their clientHello look the same as Firefox's or Chrome's?

mozkeeler commented 7 years ago

In theory, any time after the TLS handshake has completed, this information should be available, so it would be possible to do things like prevent all TLS 1.1 connections. Then again, as you said, it would be better to just set an about:config preference in that case. A web extension could also use this to block specific CAs in a way that isn't very easy with Firefox's built-in UI, but in either case there's a potential for cross-signed CAs to get around these kinds of blocks, so it's not clear that would be entirely effective. Long story short, though, as long as it didn't impact the TLS handshake or network performance, I think making this information available wouldn't be problematic.

You're correct that parsing certificates isn't trivial. An issue I see with that is it's hard to strike a balance between providing decoded information about the certificate that is useful while not being misleading or incomplete. For instance, as I'm sure you've heard, Chrome and Firefox don't fall back to using the subject common name for hostname matching for new certificates. Consequently, providing just the certificate's common name would be misleading and incomplete in that that's not the information the browsers are using to determine if the certificate is valid for the given hostname. Another example would be that string encodings can cause unexpected mismatches. If the decoded representation doesn't include what string type was used, one certificate can appear to be a valid issuer for another when in fact it isn't. So, if certificate decoding is something that would be useful in this API, we should take some care in defining what it exposes.

I agree about the tlsVersion field.

Whatever we call the chainValid or valid field, it should be clear when the user has added a verification failure override.

I don't think there's an increased privacy risk of this vs. an add-on that can inspect and modify your traffic.