Closed Bug 1606802 Opened 5 years ago Closed 2 years ago

Security exception for preloaded HSTS certificate not working after untrusting CA

Categories

(Core :: Security: PSM, defect)

68 Branch
defect
Not set
normal

Tracking

()

RESOLVED WONTFIX

People

(Reporter: estellnb, Assigned: richard)

Details

Attachments

(1 file, 2 obsolete files)

User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0

Steps to reproduce:

I have deleted all default certificates by compiling libnssckbi.so with an empty lib/ckfw/builtins/certdata.txt. This was necessary because there are many rogue certificates among these. If I visit now a site I can acknowledge individual site certificates one by one. Unfortunately this does not work for all sites. It does not work for mail.dotplex.com, for amazon.com and similar site like google.com or qwant.com.

Actual results:

I get the error SEC_ERROR_UNKNOWN_ISSUER. As far as good; I can add the required CAs with certutil. For SEC_ERROR_UNKNOWN_ISSUER it should suffice to add with -t "c,," as we do not want to trust these certification authorities. They could be rogue CAs. However if I add with "c,," I still get SEC_ERROR_UNKNOWN_ISSUER while adding with "C,," does not give that error. However adding the CA as trusted CA is worthless because then Firefox accepts all certs from this CA without warning.

Expected results:

This is a bug. SEC_ERROR_UNKNOWN_ISSUER says that the issuer is unknown and not that the issuer must be a trusted one. Please make Firefox search all issuer CAs, also untrusted ones or allow to ignore this error message by allowing to manually accept these certificates.

Component: Untriaged → Security: PSM
Product: Firefox → Core

SEC_ERROR_UNKNOWN_ISSUER is the error Firefox uses to indicate that no trusted issuer could be found, which is the situation you're describing, as far as I can tell (the algorithm can't differentiate between "the trust bits were removed from this certificate" and "there exists a path to a trusted certificate, but it requires an intermediate certificate we're not aware of").

That said, what you're describing is not a supported configuration of Firefox. Accepting each site's certificate one-by-one is not secure (how do you know a network attacker hasn't intercepted your connection and replaced the real certificates with their own?)

Status: UNCONFIRMED → RESOLVED
Closed: 5 years ago
Resolution: --- → INVALID

I use DANE to acknowledge individual certificates and on a secure computer I only visit a restricted number of sites.
This is an error. Please fix.

It is a shame that Mozilla compromises the security of those who need it most! Comparing the sha256 hash and accepting user picked certificates is currently the only way to be secure with Firefox.

It should be possible to add a manual security exception for HSTS (HTTP Strict Transport Security) sites as is possible for any other site in the web. Manually acknowledged sites are most trustworthy since it is the user on his own who has acknowledged access rights. You are not forbidden to visit a site hosted via pure http either. It is scorn to the ordinary user that something which pretends to provide elevated security does actually compromise the security of users who care the most about it.

This is not an invalid report. Please reopen quickly!

Flags: needinfo?(dkeeler)

If you want to trust individual server certificates, you should be able to do so using certutil as you've described in comment 0.

Again, though, what you're describing is not a supported way to operate Firefox. We have a limited amount of engineering resources, and this is not something we're going to spend time on.

Flags: needinfo?(dkeeler)

You can add user certificates with certutil -t "P,," to the database and they will be displayed correctly as trusted server certificates. However when you try to connect to such a site you get a warning as if these certificates would not be present at all. Fortunately this is a non-fatal bug and you can accept these peer certificates manually after comparing the sha256 hash of these certs. It is different with HSTS certificates: You can currently neither add a user exception for them nor add the required CAs in untrusted mode to the database. If you do currently not have the resources to fix this bug please mark as WONTFIX, and not as resolved invalid. I would lovingly like to try to approach a fix on my own but unfortunately I do not have the resources to do so at the moment. My computers are currently under heavy attack and I have already had to wrack two operating system installations.

First off, there are no "HSTS certificates" but there is a "Strict-Transport-Security" aka "HSTS" HTTP header. What you are probably running into is section 8.4 of RFC 6797 that states:

8.4. Errors in Secure Transport Establishment

When connecting to a Known HSTS Host, the UA MUST terminate the
connection (see also Section 12 ("User Agent Implementation Advice"))
if there are any errors, whether "warning" or "fatal" or any other
error level, with the underlying secure transport. For example, this
includes any errors found in certificate validity checking that UAs
employ, such as via Certificate Revocation Lists (CRLs) [RFC5280], or
via the Online Certificate Status Protocol (OCSP) [RFC2560], as well
as via TLS server identity checking [RFC6125].

However, I cannot trigger the behaviour described in comment 7 using Firefox 72.0.1.

I created https://self-signed.vdberg.org/ which has a certificate signed by my untrusted Test CA. I also created https://hsts-test.vdberg.org/ which additionally sends a Strict-Transport-Security HTTP header. For both sites Firefox displays "Warning: Potential Security Risk Ahead" and after selecting "Advanced" the "Error code: SEC_ERROR_UNKNOWN_ISSUER" you mentioned. In both cases I can still select "Accept the Risk and Continue" option and Firefox will create an exception for the site.

I was able to reproduce the scenario in comment 7 after all. It has to do with preloaded HSTS certificates, see https://hstspreload.org/

For example: gmail.com is an HSTS preloaded certificate that is signed by "GlobalSign Root CA - R2".

To reproduce the issue:

  1. In about:preferences#privacy -> View Certificates -> Authorities -> GlobalSign Root CA - R2 -> Edit Trust -> Uncheck "This certificate can identify websites."
  2. Visit https://gmail.com/
  3. Firefox now displays "Did Not Connect: Potential Security Issue" and the "Advanced" section has no "Accept the Risk and Continue" option
  4. In about:preferences#privacy -> View Certificates -> Servers -> Add Exception -> Enter https://gmail.com/ as Location -> Get Certicate -> Confirm Security Exception
  5. Visit https://gmail.com/
  6. Firefox still displays "Did Not Connect: Potential Security Issue"

The bug here is that for preloaded HSTS certificates the user has to trust the CA to be able to visit the site. Only trusting the server certificate should be enough though.

Status: RESOLVED → REOPENED
Ever confirmed: true
Resolution: INVALID → ---
Summary: SEC_ERROR_UNKNOWN_ISSUER though all CA certs have been loaded → Unable to add exception for preloaded HSTS certificate after untrusting CA
Summary: Unable to add exception for preloaded HSTS certificate after untrusting CA → Security exception for preloaded HSTS certificate not working after untrusting CA

This bug boils down to a narrow interpretation of section 12.1 of RFC 6797. This states "the user should not be presented with a dialog giving her the option to proceed". Nowhere does the RFC state or imply that a manually added and approved server certificate should not be allowed.

I've attached a patch that allows the site to be visited in such situation. If the root CA is not trusted and no server certificate has been added and manually approved by the user RFC 6797 is respected and no "Add Exception" option is being offered.

Assignee: nobody → richard
Status: REOPENED → ASSIGNED

Currently if a server has HSTS preloading or HPKP enabled and the user
untrusts the CA the site cannot be visited. Visiting such server should
still be possible if the user manually adds an exception for the server
certificate.

Attachment #9121781 - Attachment is obsolete: true

The priority flag is not set for this bug.
:keeler, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(dkeeler)

The way to explicitly manually trust a server certificate when you don't trust the CA is to use certutil as described in comment 0 (as I've already said in comment 6). The certificate error exception mechanism is not the way to do what you want, and attachment 9121783 [details] removes an important security check in our implementation.

Again, removing the trust settings from the certificate authorities shipped with Firefox is not a supported mode of operation. This is not a bug in Firefox. Please do not reopen this bug.

Status: ASSIGNED → RESOLVED
Closed: 5 years ago5 years ago
Flags: needinfo?(dkeeler)
Resolution: --- → INVALID

If Google Chrome implements it the way that you can manually acknowledge HSTS certificates I ask you why Firefox can´t? You know yourself that this so called "security feature" does in deed compromise security. Please do also not mark as invalid as the originally stated bug - as you have said by your own - is still unresolved.

Richard, can you use your test environment and try setting the about:config pref network.stricttransportsecurity.preloadlist to false?

For me, if I set GlobalSign Root CA R2 to not be trusted, then set network.stricttransportsecurity.preloadlist to false, I can still click-through and trust individual preloaded-HSTS sites at .google (e.g., https://about.google) issued through that root.

Flags: needinfo?(richard)

Using Firefox 75 I am no longer able to remove the trust of a builtin CA. I can edit the trust bits in the GUI, remove the entire cert using the GUI or certutil. Doesn't matter though, it gets added right back and I can still visit sites with a trust chain to that CA.

What version of FF are you testing with and how do you remove the trust bits?

Flags: needinfo?(richard)

If you un-check the websites trust bit for the CA you want to distrust, clear your cache, and visit a website that uses that CA, what is the chain of certificates you see when you click the site identity icon (lock), click the right arrow, click "more information", and click "view certificate"?

Flags: needinfo?(richard)

Thanks, I was missing that empty cache step. I now see the behaviour jcj describes. With network.stricttransportsecurity.preloadlist set to false I can click through, add a security exception and visit the site. This makes sense because in this situation no site qualifies as HSTS preloaded (because the list is not loaded).

IMHO this is not a valid workaround for this bug. In order to be able distrust a single CA (which seems to be non-permanent in FF 75) you need to give up the HSTS preload list for all CA's.

Flags: needinfo?(richard) → needinfo?(jjones)

After playing around with certutil some more I was able to make a permanent adjustment in the trust of a builtin CA by using:

certutil -d /path/to/profile.default -M -t 'c,c,c' -n "name of CA"

Changes made to builtin CA's in the GUI are reset upon restart.
Changes made to builtin CA's using certutil survive a restart.
Builtin CA's deleted by either the GUI or certutil are readded upon restart.

Changes to the trust bits of certificates in the built-in module should persist in the cert9.db file in your profile. Are your profile and that file writable?

Flags: needinfo?(richard)

Yes, I am running both FF and certutil under the same user account. The timestamp of cert9.db is updated when I change the trust bits in the FF GUI. certutil -L shows they are not changed though, they always display as ',,' which seems to be the default.

Flags: needinfo?(richard)

Are there any errors in the browser console (tools -> web developer -> browser console)?
Also, which "security device" is the certificate you're trying to change on? (second column in the authorities tab of the certificate manager)

Flags: needinfo?(richard)

(In reply to Richard van den Berg from comment #19)

Thanks, I was missing that empty cache step. I now see the behaviour jcj describes. With network.stricttransportsecurity.preloadlist set to false I can click through, add a security exception and visit the site. This makes sense because in this situation no site qualifies as HSTS preloaded (because the list is not loaded).

OK, thanks, just making sure this code path is doing the things we all think it's doing.

Changes made to builtin CA's in the GUI are reset upon restart.
Changes made to builtin CA's using certutil survive a restart.
Builtin CA's deleted by either the GUI or certutil are readded upon restart.

Editing the trust bits from the UI should persist. It does for me, in two profiles. The "delete" mechanism likely causes the edits to the trust bits to be lost, but I haven't confirmed that. Built-in roots can't be deleted, despite what the UI shows, so one should only ever edit the trust bits on built-ins.

IMHO this is not a valid workaround for this bug. In order to be able distrust a single CA (which seems to be non-permanent in FF 75) you need to give up the HSTS preload list for all CA's.

I understand that this isn't a good workaround, but despite the concreteness of your patch, I was still a little confused as to the exact scenario here. Now I am not confused, and I believe I know how to make this do what you're asking, but it's a bit more plumbing than your existing patch:

AuthCertificateParseResults would need to receive a boolean like isDirectlyTrusted coming from whether builtCertChain is longer than one entry in SSLServerCertVerificationJob::Run, and then plumb that boolean down to the OverrideAllowedForHost method and let it skip the pin checks when set.

However, even with the above plumbing and a suitable test, I do not expect we would approve such a patch. Per Elmar's request earlier, I agree this is a valid ask, although I imagine we can all admit this is a narrow use-case. I am changing this to WONTFIX, and I'm sorry to disappoint you. I dislike making such calls, but maintenance burden is real -- and a substantial concern, particularly with security-critical code like PSM.

Flags: needinfo?(jjones)
Resolution: INVALID → WONTFIX

Regarding the trust bit persistence: this seems to be an issue with my profile. With a new profile it works as expected. In my profile I get this error after an edit:

Component returned failure code: 0x805a1f65 [nsIX509CertDB.setCertTrust] editcacert.js:53
    onDialogAccept chrome://pippki/content/editcacert.js:53
    _fireButtonEvent chrome://global/content/elements/dialog.js:529
    _doButtonCommand chrome://global/content/elements/dialog.js:508
    _handleButtonCommand chrome://global/content/elements/dialog.js:502
    _handleButtonCommand self-hosted:875
    editCerts chrome://pippki/content/certManager.js:335
    oncommand chrome://pippki/content/certManager.xhtml:1

Regarding the WONTFIX: I understand your reasoning although I think it is a shame that this is the final outcome. This bug effectively prohibits an end user to manually distrust a builtin CA. Chrome and Safari have this implemented correctly. I was hoping Mozilla would value end user empowerment in this regard.

Flags: needinfo?(richard)

There should be a "distrust all" button to distrust all default CAs and only add known good ones. This would be the way to go because removing every single known-bad CA is undoable or at least ineffective in practice.

I have just set network.stricttransportsecurity.preloadlist=false with Firefox 102.12.0 but was denied access due to HSTS for a certain site with no option to accept the certificate, although I had reloaded it with Ctrl-Shift-R

Status: RESOLVED → REOPENED
Resolution: WONTFIX → ---

The following patch is waiting for review from reviewers who are inactive or resigned from the review:

ID Title Author Reviewer Status
D60382 Bug 1606802 - Honor manual server certificate exceptions for HSTS and HPKP sites richard jcj: Resigned from review
kjacobs: Resigned from review

:richard, could you please find another reviewer or abandon the patch if it is no longer relevant?

For more information, please visit BugBot documentation.

Flags: needinfo?(richard)
Attachment #9121783 - Attachment is obsolete: true

(In reply to Elmar Stellnberger from comment #27)

I have just set network.stricttransportsecurity.preloadlist=false with Firefox 102.12.0 but was denied access due to HSTS for a certain site with no option to accept the certificate, although I had reloaded it with Ctrl-Shift-R

You'll have to clear the saved HSTS information (Ctrl-Shift-R doesn't clear that, I believe). Try History -> Clear Recent History -> Cache.

Status: REOPENED → RESOLVED
Closed: 5 years ago2 years ago
Flags: needinfo?(richard)
Resolution: --- → FIXED
Resolution: FIXED → WONTFIX
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: