Leaking size of cross-origin resources by using Range Requests and Service Workers
Categories
(Core :: Audio/Video: Playback, defect)
Tracking
()
People
(Reporter: luan.herrera, Assigned: karlt, NeedInfo)
References
()
Details
(Keywords: csectype-sop, sec-high, Whiteboard: [reporter-external] [client-bounty-form] [verif?][adv-main101+][adv-esr91.10+], [wptsync upstream])
Attachments
(7 files)
(deleted),
text/html
|
Details | |
(deleted),
text/javascript
|
Details | |
(deleted),
text/x-phabricator-request
|
tjr
:
approval-mozilla-beta+
tjr
:
sec-approval+
|
Details |
(deleted),
text/x-phabricator-request
|
Details | |
(deleted),
text/x-phabricator-request
|
Details | |
(deleted),
patch
|
RyanVM
:
approval-mozilla-esr91+
|
Details | Diff | Splinter Review |
(deleted),
text/plain
|
Details |
When a cross-origin resource is used in an audio/video tag, a request containing the Range header asking for "bytes=0-" is issued.
If the request is intercepted using a Service Worker and we respond with an arbitrary Content-Range header, e.g:
e.respondWith(new Response("A", {status: 206, headers: { "Content-Range": "bytes 0-1/5000", "Content-Type": "audio/mp4" }}));
Firefox will be tricked into thinking it got the first byte of the audio/video and then ask for the remaining bytes by issuing a new request containing the "Range: bytes=1-" header.
If we decide not to intercept the subsequent request, it will go directly to the server and ask for the remaining bytes, and the response will contain bytes ranging from 1 to the total bytes of the cross-origin response.
If the total number of bytes from the cross-origin response is smaller than the total amount we stipulated when we intercepted the initial ranged request, Firefox will be fooled into thinking it needs to request more bytes, and the target's server will throw a "416 Range Not Satisfiable" error response code as it is not able to fulfill the request (as it already sent all bytes for that particular request).
We can detect when this behavior happens by counting the number of resources in performance.getEntries(), allowing an attacker to leak the exact size of cross-origin resources that accept range requests.
In the PoC, the size of https://www.google.com/robots.txt is being brute-forced starting on byte 7260. In a real attack, it would be trying to get the size through binary search.
This vulnerability is useful for XS-Search attacks. A real-world example is https://medium.com/@luanherrera/xs-searching-googles-bug-tracker-to-find-out-vulnerable-source-code-50d8135b7549 (more on https://github.com/xsleaks/xsleaks/wiki/Real-World-Examples).
This is a variation of a bug I reported to Chrome a few years ago (https://bugs.chromium.org/p/chromium/issues/detail?id=990849).
Here's a video reproducing the issue:
https://youtu.be/pj2tvVRzglg
VERSION
Version: 93.0 (64-bit)
Operating System: Windows 10
REPRODUCTION CASE
- Access https://lbherrera.github.io/lab/firefox/range-0553e1f/index.html
- Click on the "check" button and after a moment you should see messages about the leaked size of the cross-origin resource.
I have also attached the files used in the PoC - if you prefer, you can reproduce the attack by downloading and hosting index.html and sw.js on a web server.
CREDIT INFORMATION
Reporter credit: Luan Herrera (@lbherrera_)
Reporter | ||
Comment 1•3 years ago
|
||
Updated•3 years ago
|
Updated•3 years ago
|
Comment 2•3 years ago
|
||
Looking at the Chromium discussion, it seems that we need to produce performance entries also when the server returns a 416 response. I'm not sure what the right component for that is.
Updated•3 years ago
|
Comment 3•3 years ago
|
||
I think the fundamental problem here (as also detailed in the Chromium bug mentioned above in a comment by Jake) is https://github.com/whatwg/fetch/issues/144#issuecomment-368040980. There was some work on addressing this in the HTML standard for media elements in https://github.com/whatwg/html/pull/2814 but that has stalled unfortunately. Nevertheless, we need to address it in Firefox. Allowing opaque and non-opaque responses to be mixed is dangerous.
Luan, did you report this bug to Chrome as well? Because it sounds like they didn't go for the fix Jake recommend and instead addressed the symptom, which I would expect not to work long term.
Updated•3 years ago
|
Reporter | ||
Comment 4•3 years ago
|
||
(In reply to Anne (:annevk) from comment #3)
I think the fundamental problem here (as also detailed in the Chromium bug mentioned above in a comment by Jake) is https://github.com/whatwg/fetch/issues/144#issuecomment-368040980. There was some work on addressing this in the HTML standard for media elements in https://github.com/whatwg/html/pull/2814 but that has stalled unfortunately. Nevertheless, we need to address it in Firefox. Allowing opaque and non-opaque responses to be mixed is dangerous.
Luan, did you report this bug to Chrome as well? Because it sounds like they didn't go for the fix Jake recommend and instead addressed the symptom, which I would expect not to work long term.
Hey Anne, a few days after submitting this report I found a different variation that works on Chrome and sent a report to them as well. As far as I can tell, the fix they plan will require a spec change (they said they have an agreement from Mozilla and the spec editor to make this change via private communication), but it seems it will tackle the symptom and not https://github.com/whatwg/html/pull/2814.
Comment 5•3 years ago
|
||
The severity field is not set for this bug.
:bryce, could you have a look please?
For more information, please visit auto_nag documentation.
Comment 6•3 years ago
|
||
Paul, any thoughts here, sounds like we might need to wait on some spec changes to address.
Comment 7•3 years ago
|
||
I don't think we should wait for specifications to change as fixing this there is quite involved and hasn't been prioritized. (This area has been known to be problematic for at least five years.)
- Jake's fundamental fix is essentially not allowing mixing of non-opaque and opaque responses in media elements. Arguably one problem here is that the cross-origin request is still made. It seems like it should be possible to network error earlier when we detect a cross-origin request after we've started using same-origin responses.
- There's another solution to this problem outside of media elements, which is that we fix Resource Timing along the lines suggested in https://github.com/w3c/resource-timing/issues/165, but it's not clear to me that it could not be exploited in other ways. E.g., it seems timing the cross-origin response might also give the attacker some information about whether it's a 206 or 416. (There's also https://github.com/whatwg/fetch/pull/1311 about exposing network errors to Resource Timing as well, but there's no agreement on that yet.)
Comment 8•3 years ago
|
||
(In reply to Anne (:annevk) from comment #7)
It seems like it should be possible to network error earlier when we detect a cross-origin request after we've started using same-origin responses.
Probably, as long as this has no Web Compat implications, it was an issue last time.
Comment 10•3 years ago
|
||
After some discussion, we're going to take a shot at implementing option #1 in comment 7.
Updated•3 years ago
|
Updated•3 years ago
|
Assignee | ||
Comment 11•3 years ago
|
||
Firefox adds ResourceTiming entries for both 206 and 416 responses.
In Firefox, a shorter than ServiceWorker-exagerated cross-origin resource is distinguishable due to Firefox making an additional range request when the cross-origin server returns a shorter response than expected.
The expected length is set based on the range total from the initial response (from the ServiceWorker in this case).
The expected length can be increased when a longer response is received, but the final assessment that could have used the total bytes received to correctly shorten the expected length is not reached before the additional request is sent due to a comparison based on the incorrect length.
Assignee | ||
Updated•3 years ago
|
Assignee | ||
Updated•3 years ago
|
Assignee | ||
Updated•3 years ago
|
Assignee | ||
Updated•3 years ago
|
Assignee | ||
Comment 12•3 years ago
|
||
(In reply to Anne (:annevk) from comment #7)
- Jake's fundamental fix is essentially not allowing mixing of non-opaque and opaque responses in media elements.
That alone is not going to resolve the issue here as the length is already exposed to the ServiceWorker when the media element makes the additional range request (which later happens to respond with 416), so I've split this off into bug 1762068.
Arguably one problem here is that the cross-origin request is still made. It seems like it should be possible to network error earlier when we detect a cross-origin request after we've started using same-origin responses.
Filed bug 1762078 for that, addressing which would require going off spec.
This and bug 1762068 can be addressed without requiring any spec change that has not yet been agreed.
Assignee | ||
Comment 13•3 years ago
|
||
(In reply to Karl Tomlinson (:karlt) from comment #12)
(In reply to Anne (:annevk) from comment #7)
- Jake's fundamental fix is essentially not allowing mixing of non-opaque and opaque responses in media elements.
That alone is not going to resolve the issue here as the length is already exposed to the ServiceWorker when the media element makes the additional range request (which later happens to respond with 416), so I've split this off into bug 1762068.
I was wrong here. That additional range request is not made when bug 1762068 is addressed, so I'll fold bug 1762068 into this.
I'll address comment 11 in bug 1765025.
Assignee | ||
Comment 15•3 years ago
|
||
Assignee | ||
Comment 16•3 years ago
|
||
to work around https://bugzilla.mozilla.org/show_bug.cgi?id=1129121
Depends on D143865
Assignee | ||
Comment 17•3 years ago
|
||
Depends on D143866
Assignee | ||
Comment 18•3 years ago
|
||
Comment on attachment 9272577 [details]
Bug 1735923 - error on opacity change r?edenchuang
Security Approval Request
- How easily could an exploit be constructed based on the patch?: Comments in the patch describe the flaw but do not have all the details on how to exploit the flaw. Info on how to construct media resource leading bytes to exploit the flaw are public at https://github.com/whatwg/fetch/issues/144#issuecomment-368040980 and bug 1441153 comment 0. These are not referenced in the patch.
This bug report identifies a further exploit, which is similar but different to a public Chrome issue..
The patch changes the results of a test that uses related techniques, but still different from the exploits mentioned here.
- Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: Yes
- Which older supported branches are affected by this flaw?: All
- If not all supported branches, which bug introduced the flaw?: None
- Do you have backports for the affected branches?: Yes
- If not, how different, hard to create, and risky will they be?: The surrounding code has not changed since June 2019, so any conflicts for backports should be limited to expected test results.
- How likely is this patch to cause regressions; how much testing does it need?: Gecko already has reasonably different behavior with range requests in ServiceWorker, so I'm not expecting sites to be depending on Gecko's vulnerable behavior.
If any sites are depending on the vulnerable behavior, then I don't know how we could continue to support them.
The key area of risk might be if the patch should error on media element load in an unintentional situation. Existing tests were helpful in identifying flaws in previous iterations of this patch.
- Is Android affected?: Yes
Comment 19•3 years ago
|
||
Comment on attachment 9272577 [details]
Bug 1735923 - error on opacity change r?edenchuang
Approved to land and uplift
Comment 20•3 years ago
|
||
error on opacity change r=edenchuang
https://hg.mozilla.org/integration/autoland/rev/56757e00ffb4fbea5c67b67d86d081949065dd6d
https://hg.mozilla.org/mozilla-central/rev/56757e00ffb4
Comment 21•3 years ago
|
||
Landed for 101.0b3.
https://hg.mozilla.org/releases/mozilla-beta/rev/cc3d50e3408b
Please nominate this for ESR uplift too when you get a chance.
Assignee | ||
Comment 22•3 years ago
|
||
Assignee | ||
Comment 23•3 years ago
|
||
Comment on attachment 9275133 [details] [diff] [review]
error on opacity change - for esr91
ESR Uplift Approval Request
- If this is not a sec:{high,crit} bug, please state case for ESR consideration: sec-high
- User impact if declined:
- Fix Landed on Version: 102
- Risk to taking this patch: Medium
- Why is the change risky/not risky? (and alternatives if risky): The key area of risk might be if the patch should cause error on media element load in an unintentional situation. Existing tests were helpful in identifying flaws in previous iterations of this patch.
Comment 24•3 years ago
|
||
Comment on attachment 9275133 [details] [diff] [review]
error on opacity change - for esr91
Approved for 91.10esr.
Comment 25•3 years ago
|
||
uplift |
Comment 26•3 years ago
|
||
backout |
Backed out from ESR for causing test_midflight_redirect_blocked.html failures.
https://hg.mozilla.org/releases/mozilla-esr91/rev/c5fe204aa88c475fcea7e59cf34b1899bb3d6776
Log:
https://treeherder.mozilla.org/logviewer?job_id=376969368&repo=mozilla-esr91&lineNumber=4269
Assignee | ||
Comment 27•3 years ago
|
||
Ah, sorry. We need to uplift the fix for bug 1764515 before landing this on esr91.
Updated•3 years ago
|
Updated•3 years ago
|
Comment 28•3 years ago
|
||
Verified as fixed on Windows 10 x64, macOS 11.6 and on Ubuntu 20.04 x64.
Comment 29•3 years ago
|
||
(In reply to Karl Tomlinson (:karlt) from comment #27)
Ah, sorry. We need to uplift the fix for bug 1764515 before landing this on esr91.
Assuming this needs Ryan's attention then?
Comment 30•3 years ago
|
||
uplift |
Re-landed with bug 1764515 included.
https://hg.mozilla.org/releases/mozilla-esr91/rev/9f143c561b4b
Comment 31•3 years ago
|
||
Verified as fixed on Windows 10 x64, macOS 11.6 and on Ubuntu 20.04 x64.
Updated•2 years ago
|
Updated•2 years ago
|
Comment 32•2 years ago
|
||
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Comment 33•2 years ago
|
||
Comment 35•2 years ago
|
||
Backed out for causing wpt failures at fetch-canvas-tainting-video-with-range-request.https.html.
Backout link: https://hg.mozilla.org/integration/autoland/rev/d31325fafb89f1f88e5ebcb4e27bd9acfbba9f97
Failure log: https://treeherder.mozilla.org/logviewer?job_id=402723251&repo=autoland&lineNumber=9377
Comment 37•2 years ago
|
||
Comment 38•2 years ago
|
||
Backed out 2 changesets (Bug 1735923) for causing failures in fetch-canvas-tainting-video-with-range-request.https.html CLOSED TREE
Log: https://treeherder.mozilla.org/logviewer?job_id=402748729&repo=autoland&lineNumber=15318
And possible https://treeherder.mozilla.org/logviewer?job_id=402742037&repo=autoland&lineNumber=12465 which points a high frequency since this bug originally landed
Backout: https://hg.mozilla.org/integration/autoland/rev/bafeaf331566e802a4de32808818017479ef81fe
Description
•