Closed Bug 2037290 (CVE-2026-12305) Opened 6 months ago Closed 5 months ago

Multiple unchecked Top DICT offsets in cairo CFF subsetter

Categories

(Core :: Graphics: Text, defect)

Firefox 152
defect

Tracking

()

RESOLVED FIXED
153 Branch
Tracking Status
firefox-esr115 --- wontfix
firefox-esr140 152+ fixed
firefox151 --- wontfix
firefox152 + fixed
firefox153 + fixed

People

(Reporter: zzjas98, Assigned: jfkthame)

References

Details

(Keywords: csectype-bounds, reporter-external, sec-moderate, Whiteboard: [adv-main152+][adv-esr140.12+])

Attachments

(4 files, 3 external files)

Attached file cairo-poc-private.otf —

Steps to reproduce:

With an ASan build of Firefox:

  • cp cairo-poc-fdselect-offset.otf cairo-poc-private.otf ~/.fonts and fc-cache -f. This installs the malicious font.
    • To uninstall, rm ~/.fonts/cairo-poc-*.otf && fc-cache -f
  • Load file:///path/to/private.html or file:///path/to/fdselect-offset.html
  • Print -> (Save as PDF) Save -> Save

Actual results:

For private.html:

==915016==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7376a7489a73 at pc 0x71468d252761 bp 0x7ffe1dffb5d0 sp 0x7ffe1dffb5c8
READ of size 1 at 0x7376a7489a73 thread T0
    #0 0x71468d252760 in operand_length .../firefox/gfx/cairo/cairo/src/cairo-cff-subset.c:362:9
    #1 0x71468d252760 in cff_dict_read .../firefox/gfx/cairo/cairo/src/cairo-cff-subset.c:665:16
    #2 0x71468d2583af in cairo_cff_font_read_private_dict .../firefox/gfx/cairo/cairo/src/cairo-cff-subset.c:925:14
    #3 0x71468d257503 in cairo_cff_font_read_top_dict .../firefox/gfx/cairo/cairo/src/cairo-cff-subset.c:1243:11
    #4 0x71468d24e95a in cairo_cff_font_read_font .../firefox/gfx/cairo/cairo/src/cairo-cff-subset.c:1359:18
    #5 0x71468d24e95a in cairo_cff_font_generate .../firefox/gfx/cairo/cairo/src/cairo-cff-subset.c:2603:14
    #6 0x71468d24e95a in _cairo_cff_subset_init .../firefox/gfx/cairo/cairo/src/cairo-cff-subset.c:2995:14
    #7 0x71468d2b42ef in _cairo_pdf_surface_emit_cff_font_subset .../firefox/gfx/cairo/cairo/src/cairo-pdf-surface.c:6249:14
    #8 0x71468d2b42ef in _cairo_pdf_surface_emit_unscaled_font_subset .../firefox/gfx/cairo/cairo/src/cairo-pdf-surface.c:7141:14
    #9 0x71468d3c580b in _cairo_sub_font_collect .../firefox/obj-ff-asan/gfx/cairo/cairo/src/./../../../../../gfx/cairo/cairo/src/cairo-scaled-font-subsets.c:733:30
    #10 0x71468d3c580b in _cairo_scaled_font_subsets_foreach_internal .../firefox/obj-ff-asan/gfx/cairo/cairo/src/./../../../../../gfx/cairo/cairo/src/cairo-scaled-font-subsets.c:1068:2

For fdselect-offset.html:

==1180712==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x718917162494 at pc 0x70d8fd057b95 bp 0x7ffdfd6b95f0 sp 0x7ffdfd6b95e8
READ of size 1 at 0x718917162494 thread T0
    #0 0x70d8fd057b94 in cairo_cff_font_read_fdselect .../firefox/gfx/cairo/cairo/src/cairo-cff-subset.c:984:12
    #1 0x70d8fd057b94 in cairo_cff_font_read_top_dict .../firefox/gfx/cairo/cairo/src/cairo-cff-subset.c:1230:18
    #2 0x70d8fd04e95a in cairo_cff_font_read_font .../firefox/gfx/cairo/cairo/src/cairo-cff-subset.c:1359:18
    #3 0x70d8fd04e95a in cairo_cff_font_generate .../firefox/gfx/cairo/cairo/src/cairo-cff-subset.c:2603:14
    #4 0x70d8fd04e95a in _cairo_cff_subset_init .../firefox/gfx/cairo/cairo/src/cairo-cff-subset.c:2995:14
    #5 0x70d8fd0b42ef in _cairo_pdf_surface_emit_cff_font_subset .../firefox/gfx/cairo/cairo/src/cairo-pdf-surface.c:6249:14
    #6 0x70d8fd0b42ef in _cairo_pdf_surface_emit_unscaled_font_subset .../firefox/gfx/cairo/cairo/src/cairo-pdf-surface.c:7141:14
    #7 0x70d8fd1c580b in _cairo_sub_font_collect .../firefox/obj-ff-asan/gfx/cairo/cairo/src/./../../../../../gfx/cairo/cairo/src/cairo-scaled-font-subsets.c:733:30
    #8 0x70d8fd1c580b in _cairo_scaled_font_subsets_foreach_internal .../firefox/obj-ff-asan/gfx/cairo/cairo/src/./../../../../../gfx/cairo/cairo/src/cairo-scaled-font-subsets.c:1068:2
    #9 0x70d8fd09b760 in _cairo_pdf_surface_emit_font_subsets .../firefox/gfx/cairo/cairo/src/cairo-pdf-surface.c:7185:14
    #10 0x70d8fd09b760 in _cairo_pdf_surface_finish .../firefox/gfx/cairo/cairo/src/cairo-pdf-surface.c:2711:14

Expected results:

No OOB reads.

Analysis

decode_integer returns a signed int (operators 28/29 decode as int16_t / int32_t):

https://searchfox.org/firefox-main/rev/8352bcb6d75d53f3e2190221b71190e47afa0bfc/gfx/cairo/cairo/src/cairo-cff-subset.c#247-267

cairo_cff_font_read_top_dict (and the per-fontdict loop in cairo_cff_font_read_cid_fontdict) takes that signed value and adds it to font->data at four sites without checking the result against [font->data, font->data_end].
The commit ee57158fb5e4 added the two-sided p < font->data || p > font->data_end check at only one sibling site — the LOCAL_SUB offset inside the private dict: https://searchfox.org/firefox-main/rev/8352bcb6d75d53f3e2190221b71190e47afa0bfc/gfx/cairo/cairo/src/cairo-cff-subset.c#929-935

The unchecked sites:

CHARSTRINGS_OP: https://searchfox.org/firefox-main/rev/8352bcb6d75d53f3e2190221b71190e47afa0bfc/gfx/cairo/cairo/src/cairo-cff-subset.c#1205-1210

CHARSET_OP: https://searchfox.org/firefox-main/rev/8352bcb6d75d53f3e2190221b71190e47afa0bfc/gfx/cairo/cairo/src/cairo-cff-subset.c#1213-1222

PRIVATE_OP (top dict): https://searchfox.org/firefox-main/rev/8352bcb6d75d53f3e2190221b71190e47afa0bfc/gfx/cairo/cairo/src/cairo-cff-subset.c#1240-1253

PRIVATE_OP (per-fontdict): https://searchfox.org/firefox-main/rev/8352bcb6d75d53f3e2190221b71190e47afa0bfc/gfx/cairo/cairo/src/cairo-cff-subset.c#1082-1102

FDSELECT_OP / FDARRAY_OP: https://searchfox.org/firefox-main/rev/8352bcb6d75d53f3e2190221b71190e47afa0bfc/gfx/cairo/cairo/src/cairo-cff-subset.c#1227-1238

I couldn't manage to trigger ASan in Firefox end-to-end for CHARSTRINGS_OP and CHARSET_OP but they might be worth fixing.
- CHARSTRINGS_OP: A statically-malformed CHARSTRINGS offset is rejected by FreeType's CFF parser before cairo's subsetter ever runs, so Firefox never embeds the font into a PDF.
- CHARSET_OP: Firefox's font-fallback policy substitutes a different family for the specific OTF used, so cairo never sees the malicious bytes.

Please let me know if I can provide any more information, thanks!

Attached file fdselect-offset.html —
Attached file private.html —
Group: core-security → gfx-core-security
Severity: -- → S2

Both of the example fonts here are rejected by OTS if we attempt to load them as webfonts. Therefore, they could only reach the cairo subsetting code if installed locally by the user.

That's not to say we shouldn't harden the subsetting code, too, but given the requirement for both local font installation and executing a print operation, neither of which can be done directly by a website without user confirmation, the risk here seems relatively low.

See Also: → 2037288
Attached file (secure) —
Assignee: nobody → jfkthame
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true

There is an r+ patch which didn't land and no activity in this bug for 1 week.
:jfkthame, could you have a look please?
If you still have some work to do, you can add an action "Plan Changes" in Phabricator.
For more information, please visit BugBot documentation.

Flags: needinfo?(lsalzman)
Flags: needinfo?(jfkthame)

Hmm, not sure what the sec-rating should be for this; to me it seems relatively low (moderate?), per comment 4. But I'll request sec-approval so the appropriate people can make the call.

Flags: needinfo?(lsalzman)
Flags: needinfo?(jfkthame)

(I'm assuming all branches are similarly affected, though have not attempted to test them all.)

Comment on attachment 9587614 [details]
(secure)

Security Approval Request

  • How easily could an exploit be constructed based on the patch?: Not easily -- the patch hints at possible overflow (out-of-bounds read) locations, but it's unclear how that would be exploited.

(In theory I think this might be part of a sandbox escape chain during printing operations, but would require significant additional steps.)

  • 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?: No
  • If not, how different, hard to create, and risky will they be?: should be simple transplant/backport
  • How likely is this patch to cause regressions; how much testing does it need?: minimal risk, just adding bounds checks
  • Is the patch ready to land after security approval is given?: Yes
  • Is Android affected?: Yes
Attachment #9587614 - Flags: sec-approval?
Attachment #9587614 - Flags: sec-approval? → sec-approval+

https://hg-edge.mozilla.org/mozilla-central/rev/358ce92cf0ba

Please add Beta and ESR140 uplift requests to this when you get a chance and give it a severity rating.

Group: gfx-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 5 months ago
Flags: needinfo?(jfkthame)
Resolution: --- → FIXED
Target Milestone: --- → 153 Branch
Attached file (secure) —
Attachment #9592531 - Flags: approval-mozilla-beta?

firefox-beta Uplift Approval Request

  • User impact if declined/Reason for urgency: potential (parent-process) out-of-bounds access during printing operations
  • Code covered by automated testing?: no
  • Fix verified in Nightly?: no
  • Needs manual QE testing?: no
  • Steps to reproduce for manual QE testing:
  • Risk associated with taking this patch: low
  • Explanation of risk level: simple addition of bounds checks
  • String changes made/needed?: none
  • Is Android affected?: yes

firefox-esr140 Uplift Approval Request

  • User impact if declined/Reason for urgency: potential (parent-process) out-of-bounds access during printing operations
  • Code covered by automated testing?: no
  • Fix verified in Nightly?: no
  • Needs manual QE testing?: no
  • Steps to reproduce for manual QE testing:
  • Risk associated with taking this patch: low
  • Explanation of risk level: simple addition of bounds checks
  • String changes made/needed?: none
  • Is Android affected?: yes
Attachment #9592532 - Flags: approval-mozilla-esr140?
Attached file (secure) —

Calling this sec-moderate, given it's unclear how exploitable the OOB access would be, and I don't think it's reachable without user interaction (triggering a print job, local font installation).

Flags: needinfo?(jfkthame)
Keywords: sec-moderate
Attachment #9592531 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9592532 - Flags: approval-mozilla-esr140? → approval-mozilla-esr140+
QA Whiteboard: [sec] [uplift] [qa-triage-done-c153/b152]
Whiteboard: [adv-main152+]
Whiteboard: [adv-main152+] → [adv-main152+][adv-esr140.12+]
See Also: → 2045711
See Also: → 2045406
Alias: CVE-2026-12305
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: