Closed Bug 1891319 (CVE-2024-5693) Opened 1 year ago Closed 1 year ago

Manipulation with Offscreen Canvas allows bypassing tainting restrictions

Categories

(Core :: Graphics: Canvas2D, defect, P2)

Firefox 124
defect

Tracking

()

RESOLVED FIXED
128 Branch
Tracking Status
firefox-esr115 127+ fixed
firefox125 --- wontfix
firefox126 --- wontfix
firefox127 + fixed
firefox128 + fixed

People

(Reporter: kirtikumar.a.r, Assigned: aosmond)

References

Details

(Keywords: csectype-sop, reporter-external, sec-moderate, Whiteboard: [adv-main127+][adv-esr115.12+])

Attachments

(4 files, 1 obsolete file)

Attached file canvas_report.zip

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36

Steps to reproduce:

  1. Download the attached ZIP
  2. Extract it into a folder
  3. Visit the path locally /canvas_report/main_entry/UntaintingFFDemo.htm

Actual results:

The tainting of the ImageData is possible due to Same-Origin-Policy Bypass

Expected results:

It should block from changing

This is from Bug 1833876

A Video PoC to view the difference between Chrome and Firefox can be found attached. The previous issue is public. This appears to be an issue on the file:/// while the network protocol is not working. This is strange because, for the network protocol, the patch is working and not for the storage and maybe some other protocols.

@Gijs, can you please help with triaging this? Thanks!

Flags: needinfo?(gijskruitbosch+bugs)

Is there a difference between how this works for offscreen canvas vs. "regular" canvas?

Group: firefox-core-security → gfx-core-security
Component: Untriaged → Graphics: Canvas2D
Flags: needinfo?(gijskruitbosch+bugs) → needinfo?(kirtikumar.a.r)
Product: Firefox → Core
Summary: Same-Origin-Policy Bypass → Manipulation with Offscreen Canvas allows bypassing tainting restrictions on file: pages

Yes, when you have the image over other protocols same as for the file: it has differences in regular and offscreen. PoC: https://drive.google.com/file/d/1L_Hu_jHm_mBYgOjFQAUOPt2CKkNLLq_P/view?usp=sharing

This poc demonstrates the difference on the 124.0.2, any other to test on?

Flags: needinfo?(kirtikumar.a.r) → needinfo?(gijskruitbosch+bugs)
Severity: -- → S2
Priority: -- → P2

I don't think I have anything to add at this point. The graphics/canvas-knowledgeable folks will look into this. bug 1558299 is potentially related.

Flags: needinfo?(gijskruitbosch+bugs)

Okay, thanks! I assume this issue was verified? I can work on other 2 vulnerability reports?

Flags: needinfo?(aosmond)

We didn't check for a null HTMLCanvasElement when caching results from drawing an HTMLImageElement:
https://searchfox.org/mozilla-central/rev/c7df16ffad1f12a19c81c16bce0b65e4a15304d0/dom/canvas/CanvasImageCache.cpp#288

So when we do the lookup for a new OffscreenCanvas, we hit the cache and avoid tainting ourselves. That is why it has to draw it to an OffscreenCanvas at least once before drawing to a second OffscreenCanvas.

Assignee: nobody → aosmond
Status: UNCONFIRMED → NEW
Ever confirmed: true
Flags: needinfo?(aosmond)
Attached file Bug 1891319.

I think this could also be triggered with an HTMLCanvasElement that creates the cache entry, is then destroyed, and recreated using the same pointer before the cache entry expires.

Comment on attachment 9397281 [details]
Bug 1891319.

Security Approval Request

  • How easily could an exploit be constructed based on the patch?: I would say easily. It is clear we didn't clear the cache when an element went away before, and a closer inspection would show that we have a null pointer as part of the key for OffscreenCanvas.
  • 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 branches (beta, release, and/or ESR) are affected by this flaw, and do the release status flags reflect this affected/unaffected state correctly?: 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?: Only ESR115 required some manual merging, nothing extensive.
  • How likely is this patch to cause regressions; how much testing does it need?: Unlikely. We have very good coverage of drawing images into a canvas, so the codepaths should be reasonably well tested.
  • Is the patch ready to land after security approval is given?: Yes
  • Is Android affected?: Yes
Attachment #9397281 - Flags: sec-approval?

Oh, that is interesting. The patch was so quick within a week it was done. This felt so good. Thank you!

To summarize the patch:

  1. It switches us to from using HTMLCanvasElement as part of the key in the CanvasImageCache to using the CanvasRenderingContext2D. This allows us to keep using a single pointer as part of the key, as well as retaining image element caching functionality for main thread OffscreenCanvas. Since that just supplies the this pointer, it should never be null avoiding the case where a cache hit from a different OffscreenCanvas will avoid tainting.

  2. It now clears any entries tied to the CanvasRenderingContext2D object in its destructor. This avoids the case where a destroyed/recreated HTMLCanvasElement (now CanvasRenderingContext2D) might have the same pointer, and thus resulting in cache hits without tainting on a different canvas. The cache entries would have been cleared after a few seconds, but that is enough time, especially when it can be repeated again and again.

(In reply to Kirtikumar Anandrao Ramchandani from comment #11)

Oh, that is interesting. The patch was so quick within a week it was done. This felt so good. Thank you!

Thank you for your report and reduced test case!

Hello,

Thank you very much for the well-summarized patch. So I assume this would be included in the upcoming advisories?

Flags: needinfo?(dveditz)

I'm rating this one "sec-moderate" based on the original testcases being limited to file:/// (see some of the see-also bugs). Kirtikumar may wish to investigate comment 9 to see if a reliable http-based testcase could be constructed, and if so we could rate this sec-high.

Comment on attachment 9397281 [details]
Bug 1891319.

sec-approval+ = dveditz

Attachment #9397281 - Flags: sec-approval? → sec-approval+

So I assume this would be included in the upcoming advisories?

It will be in the advisories of the release it is fixed in.

Kirtikumar may wish to investigate comment 9 to see if a reliable http-based testcase could be constructed, and if so we could rate this sec-high.

I assume that a poc with slight changes from Chrome Bug 40093588 and Chrome Bug 40093490 can bypass the same way and fetch the image cross-origin bypassing the SOP using canvas.

@Andrew, any possibility you can confirm if a similar idea with slight changes in it would work? In the Chrome bug, it will fetch the bitmap-wise while in this we would try to use a tainting approach of canvas drawing and fetching it.

I am not sure but earlier, a similar one can be used in this scenario to fetch details for the vulnerability of the Comment 12 which Andrew shared a description about. :)

Flags: needinfo?(aosmond)

FYI :dveditz/:aosmond This did not land in time for Fx126.
We are now in RC week for Fx126.

Flags: needinfo?(dveditz)
Flags: needinfo?(aosmond)

Can we please get this landed, Andrew? We'll need Beta and ESR115 patches created and nominated for uplift also.

Flags: needinfo?(aosmond)

Hello,

May I know when we are considering this for the advisory? If possible, can we consider the other two vulnerabilities of mine into the advisory by patching them?

Flags: needinfo?(dveditz)

I'm checking up on this. Andrew's out today but well sort this out tomorrow.

Attachment #9403042 - Flags: approval-mozilla-esr115?
Flags: needinfo?(dveditz)
Flags: needinfo?(aosmond)

esr115 Uplift Approval Request

  • User impact if declined: Sec issue
  • Code covered by automated testing: yes
  • Fix verified in Nightly: no
  • Needs manual QE test: no
  • Steps to reproduce for manual QE testing: N/A
  • Risk associated with taking this patch: Low
  • Explanation of risk level: Mostly boilerplate changes to solve unexpected use of nullptr and reused formerly stale pointers
  • String changes made/needed: None
  • Is Android affected?: yes
Group: gfx-core-security → core-security-release
Status: NEW → RESOLVED
Closed: 1 year ago
Resolution: --- → FIXED
Target Milestone: --- → 128 Branch

The patch landed in nightly and beta is affected.
:aosmond, is this bug important enough to require an uplift?

  • If yes, please nominate the patch for beta approval.
  • If no, please set status-firefox127 to wontfix.

For more information, please visit BugBot documentation.

Flags: needinfo?(aosmond)

Comment on attachment 9397281 [details]
Bug 1891319.

Beta/Release Uplift Approval Request

  • User impact if declined: Sec issue
  • Is this code covered by automated tests?: Yes
  • Has the fix been verified in Nightly?: Yes
  • Needs manual test from QE?: No
  • If yes, steps to reproduce:
  • List of other uplifts needed: None
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): Just makes us handle nullptr and stale pointer scenarios properly, the change is well contained and easily understood
  • String changes made/needed:
  • Is Android affected?: Yes
Flags: needinfo?(aosmond)
Attachment #9397281 - Flags: approval-mozilla-beta?
Attachment #9397281 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
QA Whiteboard: [post-critsmash-triage]
Flags: qe-verify-
Attachment #9403042 - Flags: approval-mozilla-esr115? → approval-mozilla-esr115+
Whiteboard: [adv-main127+]
Attached file advisory.txt (obsolete) —

Hello Tom sir,

A quick change. The vulnerability can also be exploited through the network protocol and doesn't need to be a local storage protocol i.e. file://.

Also because of the exploit idea shared in the Comment 18 which were then ported as See also because the concept shared by Andrew to exploit this is almost fitting the way.

@Andrew sir, can you please update the title? Because we researchers shouldn't update the triage details.

Flags: needinfo?(tom)
Flags: needinfo?(aosmond)
Attached file advisory.txt
Attachment #9405336 - Attachment is obsolete: true
Flags: needinfo?(tom)

Thank you very much for quick update!

Whiteboard: [adv-main127+] → [adv-main127+][adv-esr115.12+]
Alias: CVE-2024-5693

Hello,

Was this vulnerability considered for a reward? :)

Flags: needinfo?(dveditz)

(In reply to Kirtikumar Anandrao Ramchandani from comment #37)

Was this vulnerability considered for a reward? :)

No, there was no bounty request on it. Is the above a request?

If this is a concern in the future I urge you either to file issues using the bug bounty form or to mail the bugzilla link to our security mail address as described on our Client Bug Bounty page

Flags: needinfo?(dveditz) → sec-bounty?

Updating title per comment 34

Summary: Manipulation with Offscreen Canvas allows bypassing tainting restrictions on file: pages → Manipulation with Offscreen Canvas allows bypassing tainting restrictions
Flags: sec-bounty? → sec-bounty+

Hello Daniel,

Please check your mail. Thanks!

Flags: needinfo?(dveditz)

At the sec-high it includes: UXSS, cross-origin data leaks. Can we bump the severity as the exploit poc shared was demonstrating the SOP bypass of tainting?

Adding info which was shared in Comment 34 in more detail. An attacker has to use the Canvas API like getImageData to fetch the data (Just needs to be adjusted in the initial poc) where using an offscreen canvas within a web worker, you can handle image processing tasks in a separate thread. Finally, the attacker can load an image from another domain, draw it onto an offscreen canvas, manipulate it, and then use getImageData to read the pixel data. This can reveal confidential information in the image, such as QR codes, personal photos, etc. If we have to fetch something like video then frames can be done.

I don't know but maybe also side-channel attack can be possible where an attacker can measure the time it takes to draw a cross-origin image onto an offscreen canvas. By comparing the time it has taken to render for multiple images or different parts of the same image, the attacker can infer information about the size, complexity, or specific characteristics of the image.

Can be like:

function kcheckCanvas() {
    const imageData = ctx.getImageData(0, 0, width, height);
}

Please see comment 15: if you can make it work as you claim please submit a POC showing so.

Flags: needinfo?(dveditz)
Flags: needinfo?(aosmond)

Ok, I try :)

Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: