bypassCORSChecks is not cleared after a redirect
Categories
(Core :: Networking: HTTP, defect)
Tracking
()
People
(Reporter: robwu, Assigned: sstreich, NeedInfo)
References
(Regression)
Details
(Keywords: csectype-sop, regression, sec-high, Whiteboard: [post-critsmash-triage][sec-survey][adv-main79+][adv-ESR78.1+])
Attachments
(6 files, 1 obsolete file)
700 bytes,
application/zip
|
Details | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
tjr
:
approval-mozilla-beta+
tjr
:
approval-mozilla-esr78+
tjr
:
sec-approval+
|
Details | Review |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
286 bytes,
text/plain
|
Details |
I came across the bypassCORSChecks
flag and given its omnious name, I wondered whether the flag is unset when the channel is redirected. Apparently it is not, and as a result, the response of the redirect can be read by any website!
By "response", I don't just mean the immediate response; if an attacker is able to change any URL in the redirect chain, then they can read data from any other website, with cookies if desired.
This flag is only used by extension code that handles redirects, so in order to be vulnerable to the bug, a user should install an extension that performs a redirect.
STR:
- Install HTTPS Everywhere - https://addons.mozilla.org/en-US/firefox/addon/https-everywhere/
(or the attached minimal extension, in case HTTPS Everywhere version 2020.5.20 becomes unavailable) - Visit example.com and open the developer tools
- Run
await fetch("http://talkback-public.mozilla.org")
(orhttp://live.com
if you want to see that the flag persists across server-side redirects).
Expected:
- Request should fail, because the remote resource doesn't respond with CORS headers:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://talkback-public.mozilla.org/. (Reason: CORS request did not succeed).
Actual:
- Request succeeds, I am getting the response from https://crash-stats.mozilla.org/ because of this bug, triggered by the fact that HTTPS Everywhere has defined a redirect rule from talkback-public.mozilla.org to crash-stats.mozilla.org.
Regressed by bug 1450965. Fortunately this was in 69, so ESR68 is not affected. But the upcoming ESR78 will be affected unless this bug is fixed and uplifted. Since HTTPS Everywhere is installed by default in the Tor browser (based on ESR), this bug should be fixed ASAP.
Reporter | ||
Comment 1•4 years ago
|
||
This is a minimal extension that triggers the bug (to reproduce/verify the bug in case HTTPS Everywhere changes).
Reporter | ||
Comment 2•4 years ago
|
||
Given the security impact I'd rate it P1, S1, sec-high, but I'll leave that to the network and security people.
Updated•4 years ago
|
Comment 3•4 years ago
|
||
bug 1450965 introduced this, could you look into it?
Reporter | ||
Updated•4 years ago
|
Comment 4•4 years ago
|
||
To resummarize the original problem we wanted to fix with bug 1450965:
- example.com has a button to
fetch()
data from foo.com - there is an extension that redirects any request to foo.com to example.com
- internally it means that there is a request to
foo.com
which we redirect toexample.com
before even making the request tofoo.com
; this goes through a cors check and fails it because of missingAccess-Control-Allow-Origin
on (the never happening) response tofoo.com
.
- internally it means that there is a request to
Hence, we added a default trust for extensions to allow redirect of any request to any other cross-origin.
I think dropping the flag on next redirect hop is not enough to fix this.
Possible options:
- do the cross-origin request (to
foo.com
in the above example), perhaps just a HEAD, and use theAccess-Control-Allow-Origin
. But, some extensions may use a redirect like this block the request from even happening to e.g. not leak private data. We would break it. - some other more explicit mechanism (e.g. a cross-origin check API that extensions may hook into to overrule cors checks for trusted set of URIs), not backward compatible.
- we allow the bypassCORSChecks to have its effect only when the target is subsumed by the triggering principal.
Reporter | ||
Comment 5•4 years ago
•
|
||
Is it possible to fake a response without reaching the server? Something like this (intentionally 307 instead of 302/303 to preserve the request method).
HTTP/1.0 307 Internal Redirect
Access-Control-Allow-Origin: <origin here>
Access-Control-Allow-Credentials: true
Location: <redirectUrl here>
Edit: include CORS headers of course.
Comment 6•4 years ago
|
||
(In reply to Rob Wu [:robwu] from comment #5)
Is it possible to fake a response without reaching the server? Something like this (intentionally 307 instead of 302/303 to preserve the request method).
HTTP/1.0 307 Internal Redirect Access-Control-Allow-Origin: <origin here> Access-Control-Allow-Credentials: true Location: <redirectUrl here>
Edit: include CORS headers of course.
That is what the redirectTo()
API exactly does. And my first patch to fix this was about adding the Access-Control-Allow-Origin: <origin here>
"response" header. We may rather go that way and back the current solution out.
Updated•4 years ago
|
Assignee | ||
Comment 7•4 years ago
|
||
- Backed out changeset 308ef98e6e4b
- Re-Added the old Unit Test
- Add Honza Bambas (:mayhemer) solution
Updated•4 years ago
|
Assignee | ||
Comment 8•4 years ago
|
||
Depends on D79859
Reporter | ||
Comment 9•4 years ago
|
||
[Tracking Requested - why for this release]:
This bug is easily exploitable once the conditions are met, which is the case on the Tor browser.
Tom - could you assign a security rating (probably sec-high) and make sure that an ESR78-based Tor browser does NOT ship with this bug?
Comment 10•4 years ago
|
||
Yeah, this is sec-high because it's a cross-origin data leak requiring no more than usual browsing.
Assignee | ||
Comment 11•4 years ago
|
||
Assignee | ||
Comment 12•4 years ago
|
||
Depends on D80953
Updated•4 years ago
|
Assignee | ||
Comment 13•4 years ago
|
||
Depends on D79860
Reporter | ||
Comment 14•4 years ago
|
||
Please rename the patches by removing "Part x", in case they don't land together.
- D80953 "Patch 1" contains the fix and is the minimum that needs to land.
- D80954 "Patch 2" contains a regression test and may or may not land with the first patch (I recommend yes, to avoid regressions).
- D79860 "Patch 3" contains the PoC from my bug report. This should not land until the fix has become generally available to users.
- D80956 "Patch 4" contains a cleanup. This can land after patch 1 or 2, but at the very least before "Patch 3".
D79859 is obsolete now, please visit the revision and choose "Abandon" in the dropdown at the comment box. Make sure to remove the dependencies between the patch stack involving "patch 3" and "patch 4".
Assignee | ||
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Comment 15•4 years ago
|
||
Comment on attachment 9159059 [details]
Bug 1645204 - Remove bypassCORSChecks flags r=robwu
Revision D80956 was moved to bug 1648445. Setting attachment 9159059 [details] to obsolete.
Updated•4 years ago
|
Comment 16•4 years ago
|
||
Let's aim to get this into 79.
Updated•4 years ago
|
Reporter | ||
Comment 19•4 years ago
•
|
||
dragana asked a question in https://phabricator.services.mozilla.com/D80953#2485909 , but it is not clear whether that is blocking. The network changes were copied from the original patch in D79859, all of which were approved, including r=necko-reviewers
.
IMO the fix itself (D80953) is ready, but an explicit sign-off from a necko peer wouldn't hurt (even if only to confirm that the r+ from the original patch still stands).
Edit: and the functional tests from D80954 should have a small fixup following my review comments, and then land together with the actual fix, to make sure that there are no functional regressions.
Comment 20•4 years ago
|
||
(In reply to Rob Wu [:robwu] from comment #19)
Edit: and the functional tests from D80954 should have a small fixup following my review comments, and then land together with the actual fix, to make sure that there are no functional regressions.
This is a sec-high, we don't normally land tests together with the change unless they're required to keep the tree green...
Reporter | ||
Comment 21•4 years ago
•
|
||
Comment on attachment 9159056 [details]
Bug 1645204 - Fix WebRequest.jsm r=robwu
Security Approval Request
-
How easily could an exploit be constructed based on the patch?: While the patch itself does not show any code snippet that can be used to construct an exploit, the diff itself inevitably reveals that there is a vulnerability in the handling of the
redirectUrl
part of the webRequest API, and that it relates to thebypassCORSChecks
member.To exploit the vulnerability, an attacker needs to figure out that they have to control the redirect target. This part is not blatantly obvious from the patch.
But anyone who is familiar with these concepts (webRequest extension API,redirectUrl
and "bypass CORS checks") can put the pieces together and create an exploit themselves. -
Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: No
-
Which older supported branches are affected by this flaw?: ESR78, release, beta
-
If not all supported branches, which bug introduced the flaw?: bug 1450965
-
Do you have backports for the affected branches?: Yes (patch is expectedly to apply cleanly)
-
If not, how different, hard to create, and risky will they be?:
-
How likely is this patch to cause regressions; how much testing does it need?: For manual verification of the fix, run the STR from the bug report.
To test for regressions, run unit tests. Apply the following test-only patches:
- D80954 - verifies that existing functionality continues to work as intended (I still have a pending request for slightly improved test coverage, but it doesn't block the fix from landing).
- D79860 - verifies that this security bug has been fixed.
... and run all unit tests that involve this feature:
./mach test toolkit/components/extensions/test/browser/browser_ext_webRequest_redirect_mozextension.js toolkit/components/extensions/test/mochitest/test_ext_redirect_jar.html toolkit/components/extensions/test/mochitest/test_ext_webrequest_basic.html toolkit/components/extensions/test/mochitest/test_ext_webrequest_redirect_bypass_cors.html toolkit/components/extensions/test/mochitest/test_ext_webrequest_redirect_data_uri.html toolkit/components/extensions/test/mochitest/test_ext_webrequest_upgrade.html toolkit/components/extensions/test/xpcshell/test_ext_file_access.js toolkit/components/extensions/test/xpcshell/test_ext_redirects.js toolkit/components/extensions/test/xpcshell/test_ext_webRequest_permission.js
This should provide all coverage that we need.
Comment 22•4 years ago
|
||
Comment on attachment 9159056 [details]
Bug 1645204 - Fix WebRequest.jsm r=robwu
Approved to land July 16th. We'll hold the tests until October 1.
Updated•4 years ago
|
Updated•4 years ago
|
Assignee | ||
Comment 24•4 years ago
|
||
I've rebased the patch to central and verified we pass the related tests. Since we have Sec Approval to land today, can i just mark the patch "checkin-needed" or are there additional steps i need to do to get this landed today?
Comment 26•4 years ago
|
||
Or I will I guess.
https://hg.mozilla.org/integration/autoland/rev/5d5fb35f83ed07f16b4ed242e7dd7d091af16748
Comment 27•4 years ago
|
||
uplift |
Comment 28•4 years ago
|
||
uplift |
Comment 29•4 years ago
|
||
Updated•4 years ago
|
Comment 30•4 years ago
|
||
I was able to reproduce the issue on Firefox Nightly (2020-06-11) under macOS 10.15.6 by using the STR from Comment 0.
This issue is fixed and the correct blocking strings are thrown. Tests were performed on Firefox 78.1.0esr (treeherder build), Firefox 79.0b9 and Firefox 80.0a1 (2020-07-19) under macOS 10.15.6, Windows 10 and Ubuntu 20.04.
Comment 31•4 years ago
|
||
As part of a security bug pattern analysis, we are requesting your help with a high level analysis of this bug. It is our hope to develop static analysis (or potentially runtime/dynamic analysis) in the future to identify classes of bugs.
Please visit this google form to reply.
Updated•4 years ago
|
Updated•4 years ago
|
Comment 33•4 years ago
|
||
Updated•4 years ago
|
Updated•4 years ago
|
Reporter | ||
Comment 34•4 years ago
|
||
Sebastian, could you land the cleanup and unit tests? Might have had some bit rot by now.
Updated•4 years ago
|
Description
•