Closed Bug 1678545 (CVE-2021-23971) Opened 4 years ago Closed 4 years ago

Full referrer URL exposed even from websites using strict referrer policies (e.g. "no-referrer" or "strict-origin-when-cross-origin")

Categories

(Core :: DOM: Security, defect, P2)

defect

Tracking

()

RESOLVED FIXED
86 Branch
Tracking Status
firefox-esr78 - wontfix
firefox83 --- wontfix
firefox84 --- wontfix
firefox85 + wontfix
firefox86 + fixed

People

(Reporter: l.moretto88, Assigned: dimi)

Details

(4 keywords, Whiteboard: [reporter-external] [client-bounty-form] [verif?][domsecurity-active][post-critsmash-triage][adv-main86+])

Attachments

(6 files)

I discovered this issue while studying the Referrer-Policy standard (https://w3c.github.io/webappsec-referrer-policy/).

This seems to be caused by a wrong implementation of the standard, more in particular for what concerns the combination of "8.2. Set request’s referrer policy on redirect" and "8.3. Determine request’s Referrer".

If a server (also third-party ones) replies with a redirect response including a referrer-policy response header, it seems that, when computing the new referrer value for the redirected request, Firefox uses the document's URL as referrerSource, instead of the previously computed referrer value for the original request (which may even be "no-referrer"). This is in contrast with what the standard specifies and leads to this vulnerability.

You can find more details in the attached PoC's README.md file.

I verified this issue on both Firefox 78.5.0esr and latest Firefox Nightly 85.0a1.

Flags: sec-bounty?
Summary: Full referrer URL exposed even from websites using stric referrer policies (e.g. "no-referrer" or "strict-origin-when-cross-origin") → Full referrer URL exposed even from websites using strict referrer policies (e.g. "no-referrer" or "strict-origin-when-cross-origin")

Not sure off-hand whether this is in DOM Security or Networking. Dragana, can you take a look or forward to someone?

Thanks!

Group: firefox-core-security → core-security
Type: task → defect
Component: Security → Networking
Flags: needinfo?(dd.mozilla)
Product: Firefox → Core

Christoph, is this something you can look at?

Flags: needinfo?(dd.mozilla) → needinfo?(ckerschb)

Hello,
do you have any update on this?

Hello,
it's been 11 days since I reported this issue, with no feedback whatsoever until now.

Considering the simplicity of the exploit and the impact on users' security and privacy, I honestly think this does deserve some attention.

I tried my best to provide a clear explanation, root cause analysis and proof of concept code. Nonetheless I am more than willing to provide any further details that might be required.

Please let me know if I can help in any way.

(In reply to Luca Moretto from comment #4)

Hello,
it's been 11 days since I reported this issue, with no feedback whatsoever until now.

Considering the simplicity of the exploit and the impact on users' security and privacy, I honestly think this does deserve some attention.

I tried my best to provide a clear explanation, root cause analysis and proof of concept code. Nonetheless I am more than willing to provide any further details that might be required.

Please let me know if I can help in any way.

Most people were out last week as there was thanksgiving and some additional time off, I'm sure Christoph has to work through a lot of backlog from that (I do) so I'd ask for a bit more patience :)

Oh ok sorry, being in Italy I didn't think about thanksgiving, my bad :)

(In reply to Luca Moretto from comment #6)

Oh ok sorry, being in Italy I didn't think about thanksgiving, my bad :)

Hey Luca, thanks for reporting and sorry for the lag of response. Anyway, from a quick glance this looks like a bug to me, though I am surprised there is no web-platform test which would catch that issue, because there are tons of redirect tests within testing/web-platform/tests/referrer-policy.

Anway, Dimi offered to take a look at it and will investigate - moving this over to DOM:Security so we have it on our radar.

Component: Networking → DOM: Security
Flags: needinfo?(ckerschb) → needinfo?(dlee)
Group: core-security → dom-core-security

I'm confused by the spec language -- maybe it's talking about the policy set for the top-level document and not for sub-requests. We definitely don't want a site receiving a stripped referred to redirect to itself with a ReferrerPolicy header in order to expose the referrer.

Keywords: privacy

Anne: Referrer Policy updating during redirect is called from https://fetch.spec.whatwg.org/#http-redirect-fetch which is used for navigation (where this makes perfect sense) but also for everything else, where it allows a recipient to unmask the referrer by using redirects. Am I reading this wrong, or should this be restricted to destination document, frame, and iframe in either the Fetch or Referrer Policy specs?

Dimi: what is Chrome doing for this? Since all the spec editors are Chrome folks maybe that will shed light on what they meant even if it's not what they wrote.

Flags: needinfo?(annevk)

After a redirect you finally get to the non-redirecting resource itself, which can then have its own Referrer Policy (if it's a document). Why does the spec even care what kind of policy a middle-medler wants?

I am confused too by the fact that the spec would allow third parties to modify a request's associated referrer policy.

Anyway, I still think that the Firefox implementation differs from what the spec mandates. I tried to explain this in the "Vulnerability explanation" section of the attached README file. The key point is what information is used as "referrerSource" when (re)computing the referrer value.

When receiving a redirect response and updating the request for the new location, Firefox should use the request's originally computed referrer (if any). Instead, it seems that Firefox re-uses the document's url, and this is where the problem occurs.

My README file contains an example that strictly follows the algorithm as it is explained in the spec and highlights exactly where Firefox's implementation differs from the spec, and from other browsers like Chrome.

Even though the spec doesn't clearly state this, the only possible effect for a redirect response is to limit the amount of information in the referrer header, not to extend it. This can be verified by running my poc code against a browser like Chrome and using different referrer-policy combinations:

  • if the redirect referrer-policy is stricter than the document's one, the referrer will become stricter
  • if the redirect referrer-policy is looser than the document's one, the originally computed referrer (if any!) will be sent

Daniel, I think the bit you are missing is that the referrer is a field on the request. Initially that field has a special "client" value, but that gets overridden in 2.7 of https://fetch.spec.whatwg.org/#concept-main-fetch (indeed with the URL of the document in a typical case) after which it is a URL (or "no-referrer") that can stay the same or be reduced in granularity. So a redirect (by design) could not ever end up exposing more since the request does not carry that information.

(I think the reason it cares about policies from redirectors is so they can hide information from their targets. Per the specification this should also work for subresource requests, which is somewhat novel, but I think that is also intentional and therefore by design if I remember correctly. It would be good to double check with web-platform-tests as Christoph mentioned.)

Flags: needinfo?(annevk)

It looks like a bug while handling redirects. This is how we set referrer for redirects; please correct me if I am wrong:

  1. When a redirect happens, we compute the new referrer for the redirected channel by calling CreateFromOtherAndPolicyOverride.
  2. In CreateFromOtherAndPolicyOverride, we use OriginalReferrer from the old channel's ReferrerInfo and the new policy from the response to compute the new referrer of the redirect request.

Because OriginalReferrer is not trimmed, we basically expose the URL of the original document as long as the evil server overwrites the referrer-policy with redirects. I did a quick test that with the no-referrer (original referrer policy) -> unsafe-url (redirect referrer policy) combination, we still send the full URL in the final request's referrer.

According to spec, we should use request’s referrer to compute the new referrer. If I understand correctly, that corresponds to ComputedReferrer in our codebase, so we could probably fix this by using ComputedReferrer instead of OriginalReferrer in step2.

Christoph, does this make sense to you?

Flags: needinfo?(dlee) → needinfo?(ckerschb)

(In reply to Dimi Lee [:dimi][:dlee] from comment #14)

Christoph, does this make sense to you?

Yes, that seems like the root problem of the bug. I would still be curious why there is no test for that scenario. Could you please work on a fix and run the redirect web-platform tests within testing/web-platform/tests/referrer-policy. If there is no test stressing this behavior then I think we should add one. Thanks for looking into this!

Flags: needinfo?(ckerschb)
Assignee: nobody → dlee
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true
Severity: -- → S2
Priority: -- → P2
Whiteboard: [reporter-external] [client-bounty-form] [verif?] → [reporter-external] [client-bounty-form] [verif?][domsecurity-active]

Daniel, may I kindly ask why this was only labelled as sec-moderate?

Based on the severity ratings criteria (https://wiki.mozilla.org/Security_Severity_Ratings/Client#Severity_Ratings) I'd expect this to be at least marked as sec-high. In my opinion, this vulnerability:

  • can disclose sensitive user data, which may allow to uniquely identify the user (in fact you also marked it as csectype-disclosure): this does not only impact privacy, but also security, as stated in the spec (https://w3c.github.io/webappsec-referrer-policy/#intro-security) (e.g. URL based session identifiers or capability URLs)
  • can disclose the browsing history: consider for instance if a service like fonts.googleapis.com decided to exploit it. Since the service is used by quite a lot of websites, it is easy to imagine how user's browsing history may be exposed
  • is exceptionally easy to exploit: it only requires just a simple redirect response with a referrer-policy header. This may even cause it to be marked as sec-critical
Flags: needinfo?(dveditz)

It's not going to be sec-critical -- that's used for attacks the compromise the user's local machine or sometimes data.

sec-moderate might be wrong (and there's opportunity for more developers to chime in), but my starting point is that by default the web shares referrers everywhere by default. Referrer-Policy is a relatively new mitigation that sites are mostly using for privacy, not security. It's disclosing the website's data (about the user) rather than information from the user (that is, stored in Firefox) and it's not a Same-Origin-Policy bypass that gets you arbitrary data from the other website. It's a bypass for an opt-in mitigation feature and we typically cap those at sec-moderate.

Flags: needinfo?(dveditz)

(In reply to Daniel Veditz [:dveditz] from comment #19)

It's not going to be sec-critical -- that's used for attacks the compromise the user's local machine or sometimes data.

sec-moderate might be wrong (and there's opportunity for more developers to chime in), but my starting point is that by default the web shares referrers everywhere by default. Referrer-Policy is a relatively new mitigation that sites are mostly using for privacy, not security. It's disclosing the website's data (about the user) rather than information from the user (that is, stored in Firefox) and it's not a Same-Origin-Policy bypass that gets you arbitrary data from the other website. It's a bypass for an opt-in mitigation feature and we typically cap those at sec-moderate.

I must disagree with the fact that referrers are always shared by default. Being, as you say, a relatively new feature, some/many websites will fallback to using the user agent's default policy. Firefox uses no-referrer-when-downgrade by default, which at least prevents referrer sharing when navigating from https to http. This vulnerability also affects the default policy, resulting in the transmission of full https referrers unencrypted, visible not only to the malicious site but to anything/anyone in between.
Also, please note that the spec mandates to use the more secure strict-origin-when-cross-origin (https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-strict-origin-when-cross-origin) as default policy, and this is another point where Firefox (at least the versions I tried) differs from the spec.

For what concerns privacy vs. security, I think that the spec clearly suggests that website owners can rely on referrer-policy for security reasons (e.g. to include session identifiers in the URL, https://w3c.github.io/webappsec-referrer-policy/#intro-security ). As a consequence, I think it's Firefox's responsibility to respect the spec, and that failing to do so is a security vulnerability.

(The new default is a very recent change to the specification and is being tracked by bug 1589074.)

Hi Dan,
The patch for the sec-moderate bug is r+ and we would like to land the patch. Do you have any concern, or can I just land the patch? Thanks!

Flags: needinfo?(dveditz)

Dimi: there are no special concerns about landing a patch for a sec-moderate bug in general. If your own gut feeling tells you a particular bug is more sensitive than the typical sec-moderate please do trust that feeling and ask for a 2nd opinion, but I have no concerns here that would require special handling. https://firefox-source-docs.mozilla.org/bug-mgmt/processes/security-approval.html

Flags: needinfo?(dveditz)

(In reply to Luca Moretto from comment #20)

I must disagree with the fact that referrers are always shared by default.

Not "always", but "by default" that's what happens most of the time on the web since the 90s.

This vulnerability also affects the default policy, resulting in the transmission of full https referrers unencrypted, visible not only to the malicious site but to anything/anyone in between.

Yes, no one is saying this is not a security problem.

Also, please note that the spec mandates to use the more secure strict-origin-when-cross-origin

Browser vendors are cooperating to make the web a safer place than the defaults established in the 90s. We're not there yet, though, so a bug that mostly reverts people to an older state is unfortunate but it's not malware-installing unfortunate. As expectations rise (measured in years) this kind of failure would be likely considered more harshly.

This had landed:
https://hg.mozilla.org/integration/autoland/rev/2fc34c84a4e0e072842fbfc73ed374fb5caebd59
https://hg.mozilla.org/integration/autoland/rev/c3e0e7b4ef43e90d37d11dfd4c6561d648229eb7

Backed out for mochitest failures at test_referrer_redirect.html:

https://hg.mozilla.org/integration/autoland/rev/42be1816b3857a3962cd0ec4be551830b6639aee

Push with failures: https://treeherder.mozilla.org/jobs?repo=autoland&group_state=expanded&selectedTaskRun=W7d57f_HQY6l49ZBSIA62Q.1&resultStatus=testfailed%2Cbusted%2Cexception%2Cretry%2Cusercancel%2Crunnable&revision=c3e0e7b4ef43e90d37d11dfd4c6561d648229eb7
Failure log: https://treeherder.mozilla.org/logviewer?job_id=324659336&repo=autoland

[task 2020-12-16T08:58:53.643Z] 08:58:53 INFO - TEST-PASS | dom/security/test/referrer-policy/test_referrer_redirect.html | no-referrer-with-no-meta-origin-RP-header tests have to be performed.
[task 2020-12-16T08:58:53.644Z] 08:58:53 INFO - Buffered messages finished
[task 2020-12-16T08:58:53.645Z] 08:58:53 INFO - TEST-UNEXPECTED-FAIL | dom/security/test/referrer-policy/test_referrer_redirect.html | no-referrer (img/iframe) with no meta, origin Referrer-Policy redirect header --- none () - got "none", expected "origin"
[task 2020-12-16T08:58:53.645Z] 08:58:53 INFO - SimpleTest.is@SimpleTest/SimpleTest.js:500:14
[task 2020-12-16T08:58:53.646Z] 08:58:53 INFO - onload@dom/security/test/referrer-policy/referrer_helper.js:52:7
[task 2020-12-16T08:58:53.646Z] 08:58:53 INFO - doXHR/xhr.onload@dom/security/test/referrer-policy/referrer_helper.js:35:14
[task 2020-12-16T08:58:53.888Z] 08:58:53 INFO - {"origin-with-no-meta-no-referrer-RP-header":{"referrer":"","policy":"none","expected":null}}

Flags: needinfo?(dlee)
Flags: needinfo?(dlee)

The patch landed in nightly and beta is affected.
:dimi, is this bug important enough to require an uplift?
If not please set status_beta to wontfix.

For more information, please visit auto_nag documentation.

Flags: needinfo?(dlee)

given that we are still investigating whether Bug 1678545 is really a regression of this bug and people will be out next week.
I think we should not uplift the patch at this point.

Flags: needinfo?(dlee)

(In reply to Dimi Lee [:dimi][:dlee] from comment #29)

given that we are still investigating whether Bug 1678545 is really a regression of this bug [...]

That's this bug -- which bug is the possible regression?

Flags: sec-bounty?
Flags: sec-bounty+
Flags: needinfo?(dlee)

(In reply to Daniel Veditz [:dveditz] from comment #30)

(In reply to Dimi Lee [:dimi][:dlee] from comment #29)

given that we are still investigating whether Bug 1678545 is really a regression of this bug [...]

That's this bug -- which bug is the possible regression?

ah, it should be Bug 1683605, which has been confirmed that it is not related to this bug.

Flags: needinfo?(dlee)
Flags: qe-verify+
Whiteboard: [reporter-external] [client-bounty-form] [verif?][domsecurity-active] → [reporter-external] [client-bounty-form] [verif?][domsecurity-active][post-critsmash-triage]

I tried to reproduce the initial issue using the steps from README.md file in order to verify that this is fixed, but unfortunately I got stuck when accessing secure.com after adding two dummy certificates made and saved in <project dir>/secure_privkey.pem | secure_fullchain.pem | ref-stealing_privkey.pem and ref-stealing_fullchain.pem, I get Unable to connect page.
Is there something I am missing maybe (all other prerequisites were successfully done)?
Does these certificates need to have something special? The certificates were made with: openssl genrsa -des3 -out myCA.key 2048 and openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem

Flags: needinfo?(dlee)

(In reply to Bogdan Maris [:bogdan_maris], Release Desktop QA from comment #32)

Does these certificates need to have something special? The certificates were made with: openssl genrsa -des3 -out myCA.key 2048 and openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem

Sorry for the late reply.
I think you'll still have do the following after creating the CA certificate

  1. Import myCA.pem with Firefox by Preferences->View Certificates->Authorities->Import
  2. create certificate and private key for secure.com & ref-stealing.com
    ex.
    create certificate request for secure.com: openssl req -new -nodes -newkey rsa:4096 -keyout secure.key -out secure.req -batch -subj "/C=DE/ST=Berlin/L=Berlin/O=Dimi CA/OU=router/CN=secure.com" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:secure.com,IP:127.0.0.1"))
    create certificate for secure.com: openssl x509 -req -in secure.req -CA myCA.crt -CAkey myCA.key -CAcreateserial -out secure.crt -days 3650 -sha256 -extfile <(printf "subjectAltName=DNS:secure.com,IP:127.0.0.1")

if you still have any question, you can send me a mail or find me on slack

Flags: needinfo?(dlee)
Whiteboard: [reporter-external] [client-bounty-form] [verif?][domsecurity-active][post-critsmash-triage] → [reporter-external] [client-bounty-form] [verif?][domsecurity-active][post-critsmash-triage][adv-main86+]
Alias: CVE-2021-23971
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: