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)
Tracking
()
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.
Reporter | ||
Updated•4 years ago
|
Comment 1•4 years ago
|
||
Not sure off-hand whether this is in DOM Security or Networking. Dragana, can you take a look or forward to someone?
Thanks!
Comment 2•4 years ago
|
||
Christoph, is this something you can look at?
Reporter | ||
Comment 3•4 years ago
|
||
Hello,
do you have any update on this?
Reporter | ||
Comment 4•4 years ago
|
||
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.
Comment 5•4 years ago
|
||
(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 :)
Reporter | ||
Comment 6•4 years ago
|
||
Oh ok sorry, being in Italy I didn't think about thanksgiving, my bad :)
Comment 7•4 years ago
|
||
(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.
Updated•4 years ago
|
Comment 8•4 years ago
|
||
Comment 9•4 years ago
|
||
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.
Comment 10•4 years ago
|
||
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.
Comment 11•4 years ago
|
||
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?
Reporter | ||
Comment 12•4 years ago
|
||
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
Comment 13•4 years ago
|
||
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.)
Assignee | ||
Comment 14•4 years ago
|
||
It looks like a bug while handling redirects. This is how we set referrer for redirects; please correct me if I am wrong:
- When a redirect happens, we compute the new referrer for the redirected channel by calling CreateFromOtherAndPolicyOverride.
- 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?
Comment 15•4 years ago
|
||
(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!
Assignee | ||
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Reporter | ||
Comment 16•4 years ago
|
||
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
Assignee | ||
Comment 17•4 years ago
|
||
Assignee | ||
Comment 18•4 years ago
|
||
Depends on D99358
Comment 19•4 years ago
|
||
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
.
Reporter | ||
Comment 20•4 years ago
|
||
(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 atsec-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.
Comment 21•4 years ago
|
||
(The new default is a very recent change to the specification and is being tracked by bug 1589074.)
Assignee | ||
Comment 22•4 years ago
|
||
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!
Comment 23•4 years ago
|
||
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
Comment 24•4 years ago
|
||
(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.
![]() |
||
Comment 25•4 years ago
|
||
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}}
Assignee | ||
Comment 26•4 years ago
|
||
![]() |
||
Comment 27•4 years ago
|
||
https://hg.mozilla.org/integration/autoland/rev/584335a0cc1f5015d26d488938c1c6ef6de4d0a4
https://hg.mozilla.org/integration/autoland/rev/2246b7b99f0f334084ae8898d433c75234f23aa5
https://hg.mozilla.org/integration/autoland/rev/756db199e7a1d1e8b5a4199ea2f866cf3c579f22
https://hg.mozilla.org/mozilla-central/rev/584335a0cc1f
https://hg.mozilla.org/mozilla-central/rev/2246b7b99f0f
https://hg.mozilla.org/mozilla-central/rev/756db199e7a1
Assignee | ||
Updated•4 years ago
|
Updated•4 years ago
|
Comment 28•4 years ago
|
||
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.
Assignee | ||
Comment 29•4 years ago
|
||
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.
Comment 30•4 years ago
|
||
(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?
Assignee | ||
Comment 31•4 years ago
|
||
(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.
Updated•4 years ago
|
Assignee | ||
Updated•4 years ago
|
Comment 32•4 years ago
|
||
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
Assignee | ||
Comment 33•4 years ago
|
||
(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
andopenssl 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
- Import myCA.pem with Firefox by Preferences->View Certificates->Authorities->Import
- 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
Updated•4 years ago
|
Updated•4 years ago
|
Comment 34•4 years ago
|
||
Updated•4 years ago
|
Updated•3 years ago
|
Updated•9 months ago
|
Description
•