ZDI-CAN-16716: Mozilla Firefox textPath Element Use-After-Free Remote Code Execution Vulnerability
Categories
(Core :: SVG, defect)
Tracking
()
People
(Reporter: freddy, Assigned: emilio)
Details
(Keywords: csectype-uaf, sec-high)
Attachments
(2 files, 1 obsolete file)
Below is the original email from the ZDI, with some details hidden away for brevity.
VULNERABILITY DETAILS
- Version tested: 1-Mozilla Firefox release 97.0.1 (64-bit) 2-Mozilla Firefox Nightly version 99.0a1 (2022-02-21) (64-bit) [Task ID: Lh3DFe-0TUWEP14lyZDe5g, Rank: 1645479586, Changeset: ca774a5b6b7b6874f91abb76a422582d37169a57, Build ID: 20220221213946]
- Installer file: 1-"Firefox Setup 97.0.1.exe" 2-https://firefox-ci-tc.services.mozilla.com/api/queue/v1/task/Lh3DFe-0TUWEP14lyZDe5g/artifacts/public/build/target.tar.bz2
- Platform tested: Linux lab-vm 5.13.0-28-generic #31~20.04.1-Ubuntu SMP Wed Jan 19 14:08:10 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Analysis
UAF during handling of textPath element (it should crash upon loading the poc. If not, reload the page):
ASAN output:
==82318==ERROR: AddressSanitizer: heap-use-after-free on address 0x60c000085488 at pc 0x7fc2876b981a bp 0x7fff206a03d0 sp 0x7fff206a03c8
WRITE of size 1 at 0x60c000085488 thread T0 (file:// Content)
console.warn: TopSitesFeed: Failed to fetch data from Contile server: NetworkError when attempting to fetch resource.
#0 0x7fc2876b9819 in OnNonDOMMutationRenderingChange /builds/worker/checkouts/gecko/layout/svg/SVGObserverUtils.cpp:246:18
#1 0x7fc2876b9819 in mozilla::SVGRenderingObserverSet::InvalidateAll() /builds/worker/checkouts/gecko/layout/svg/SVGObserverUtils.cpp:1066:15
#2 0x7fc2876b5ef5 in mozilla::SVGTextFrame::ReflowSVGNonDisplayText() /builds/worker/checkouts/gecko/layout/svg/SVGTextFrame.cpp:2848:3
#3 0x7fc287680023 in mozilla::SVGContainerFrame::ReflowSVGNonDisplayText(nsIFrame*) /builds/worker/checkouts/gecko/layout/svg/SVGContainerFrame.cpp:114:40
#4 0x7fc2876814d3 in mozilla::SVGDisplayContainerFrame::ReflowSVG() /builds/worker/checkouts/gecko/layout/svg/SVGContainerFrame.cpp:337:11
#5 0x7fc2876c13f8 in mozilla::SVGOuterSVGFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) /builds/worker/checkouts/gecko/layout/svg/SVGOuterSVGFrame.cpp:451:14
#6 0x7fc2874fb8df in nsLineLayout::ReflowFrame(nsIFrame*, nsReflowStatus&, mozilla::ReflowOutput*, bool&) /builds/worker/checkouts/gecko/layout/generic/nsLineLayout.cpp:875:13
#7 0x7fc2872ec961 in nsBlockFrame::ReflowInlineFrame(mozilla::BlockReflowInput&, nsLineLayout&, nsLineList_iterator, nsIFrame*, LineReflowStatus*) /builds/worker/checkouts/gecko/layout/generic/nsBlockFrame.cpp:4553:15
#8 0x7fc2872eb96d in nsBlockFrame::DoReflowInlineFrames(mozilla::BlockReflowInput&, nsLineLayout&, nsLineList_iterator, nsFlowAreaRect&, int&, nsFloatManager::SavedState*, bool*, LineReflowStatus*, bool) /builds/worker/checkouts/gecko/layout/generic/nsBlockFrame.cpp:4355:5
#9 0x7fc2872e4bee in nsBlockFrame::ReflowInlineFrames(mozilla::BlockReflowInput&, nsLineList_iterator, bool*) /builds/worker/checkouts/gecko/layout/generic/nsBlockFrame.cpp:4240:9
#10 0x7fc2872de3e9 in nsBlockFrame::ReflowLine(mozilla::BlockReflowInput&, nsLineList_iterator, bool*) /builds/worker/checkouts/gecko/layout/generic/nsBlockFrame.cpp:3227:5
#11 0x7fc2872d5d9e in nsBlockFrame::ReflowDirtyLines(mozilla::BlockReflowInput&) /builds/worker/checkouts/gecko/layout/generic/nsBlockFrame.cpp:2761:7
#12 0x7fc2872cf040 in nsBlockFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) /builds/worker/checkouts/gecko/layout/generic/nsBlockFrame.cpp:1394:3
#13 0x7fc2872e94d2 in nsBlockReflowContext::ReflowBlock(mozilla::LogicalRect const&, bool, nsCollapsingMargin&, int, bool, nsLineBox*, mozilla::ReflowInput&, nsReflowStatus&, mozilla::BlockReflowInput&) /builds/worker/checkouts/gecko/layout/generic/nsBlockReflowContext.cpp:288:11
#14 0x7fc2872e15e2 in nsBlockFrame::ReflowBlockFrame(mozilla::BlockReflowInput&, nsLineList_iterator, bool*) /builds/worker/checkouts/gecko/layout/generic/nsBlockFrame.cpp:3874:11
#15 0x7fc2872de536 in nsBlockFrame::ReflowLine(mozilla::BlockReflowInput&, nsLineList_iterator, bool*) /builds/worker/checkouts/gecko/layout/generic/nsBlockFrame.cpp:3224:5
#16 0x7fc2872d5d9e in nsBlockFrame::ReflowDirtyLines(mozilla::BlockReflowInput&) /builds/worker/checkouts/gecko/layout/generic/nsBlockFrame.cpp:2761:7
#17 0x7fc2872cf040 in nsBlockFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) /builds/worker/checkouts/gecko/layout/generic/nsBlockFrame.cpp:1394:3
#18 0x7fc2872e94d2 in nsBlockReflowContext::ReflowBlock(mozilla::LogicalRect const&, bool, nsCollapsingMargin&, int, bool, nsLineBox*, mozilla::ReflowInput&, nsReflowStatus&, mozilla::BlockReflowInput&) /builds/worker/checkouts/gecko/layout/generic/nsBlockReflowContext.cpp:288:11
#19 0x7fc2872e15e2 in nsBlockFrame::ReflowBlockFrame(mozilla::BlockReflowInput&, nsLineList_iterator, bool*) /builds/worker/checkouts/gecko/layout/generic/nsBlockFrame.cpp:3874:11
#20 0x7fc2872de536 in nsBlockFrame::ReflowLine(mozilla::BlockReflowInput&, nsLineList_iterator, bool*) /builds/worker/checkouts/gecko/layout/generic/nsBlockFrame.cpp:3224:5
#21 0x7fc2872d5d9e in nsBlockFrame::ReflowDirtyLines(mozilla::BlockReflowInput&) /builds/worker/checkouts/gecko/layout/generic/nsBlockFrame.cpp:2761:7
#22 0x7fc2872cf040 in nsBlockFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) /builds/worker/checkouts/gecko/layout/generic/nsBlockFrame.cpp:1394:3
#23 0x7fc287307c3d in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, mozilla::WritingMode const&, mozilla::LogicalPoint const&, nsSize const&, nsIFrame::ReflowChildFlags, nsReflowStatus&, nsOverflowContinuationTracker*) /builds/worker/checkouts/gecko/layout/generic/nsContainerFrame.cpp:1005:14
#24 0x7fc287306417 in nsCanvasFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) /builds/worker/checkouts/gecko/layout/generic/nsCanvasFrame.cpp:787:7
#25 0x7fc287307c3d in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, mozilla::WritingMode const&, mozilla::LogicalPoint const&, nsSize const&, nsIFrame::ReflowChildFlags, nsReflowStatus&, nsOverflowContinuationTracker*) /builds/worker/checkouts/gecko/layout/generic/nsContainerFrame.cpp:1005:14
#26 0x7fc287392e86 in nsHTMLScrollFrame::ReflowScrolledFrame(mozilla::ScrollReflowInput&, bool, bool, mozilla::ReflowOutput*) /builds/worker/checkouts/gecko/layout/generic/nsGfxScrollFrame.cpp:838:3
#27 0x7fc287394489 in nsHTMLScrollFrame::ReflowContents(mozilla::ScrollReflowInput&, mozilla::ReflowOutput const&) /builds/worker/checkouts/gecko/layout/generic/nsGfxScrollFrame.cpp:973:3
#28 0x7fc28739aad4 in nsHTMLScrollFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) /builds/worker/checkouts/gecko/layout/generic/nsGfxScrollFrame.cpp:1395:3
#29 0x7fc2872bebfb in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, int, int, nsIFrame::ReflowChildFlags, nsReflowStatus&, nsOverflowContinuationTracker*) /builds/worker/checkouts/gecko/layout/generic/nsContainerFrame.cpp:1045:14
#30 0x7fc2872be229 in mozilla::ViewportFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) /builds/worker/checkouts/gecko/layout/generic/ViewportFrame.cpp:374:7
#31 0x7fc287102a29 in mozilla::PresShell::DoReflow(nsIFrame*, bool, mozilla::OverflowChangedTracker*) /builds/worker/checkouts/gecko/layout/base/PresShell.cpp:9542:11
(...)
SUMMARY: AddressSanitizer: heap-use-after-free /builds/worker/checkouts/gecko/layout/svg/SVGObserverUtils.cpp:246:18 in OnNonDOMMutationRenderingChange
CREDIT
This vulnerability was discovered by:
Hossein Lotfi of Trend Micro Zero Day Initiative
Reporter | ||
Comment 1•3 years ago
|
||
Reporter | ||
Updated•3 years ago
|
Assignee | ||
Updated•3 years ago
|
Assignee | ||
Updated•3 years ago
|
Assignee | ||
Updated•3 years ago
|
Assignee | ||
Comment 2•3 years ago
|
||
InvalidateAll() would call into our observers and potentially reflow
here:
Which could delete our continuations while we have a reference to the
observer on the stack.
Assignee | ||
Updated•3 years ago
|
Updated•3 years ago
|
Updated•3 years ago
|
Assignee | ||
Comment 3•3 years ago
|
||
Comment on attachment 9265163 [details]
Bug 1756793 - Make SVGObserverUtils::GetAndObserveTextPathsPath not observe on continuations. r=jwatt,jfkthame
Security Approval Request
- How easily could an exploit be constructed based on the patch?: Not super-easily, but easily enough for someone with deep layout knowledge.
- 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?: 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?: Should apply cleanly.
- How likely is this patch to cause regressions; how much testing does it need?: not very likely.
Assignee | ||
Comment 4•3 years ago
|
||
For reference, extended commit message which will be deleted is in comment 2.
Comment 5•3 years ago
|
||
This seems to be the same root issue as bug 1736243 - per discussions with emilio/dveditz, let's move the patch over there and mark this as a duplicate.
Comment 6•3 years ago
|
||
Comment on attachment 9265163 [details]
Bug 1756793 - Make SVGObserverUtils::GetAndObserveTextPathsPath not observe on continuations. r=jwatt,jfkthame
Revision D139485 was moved to bug 1736243. Setting attachment 9265163 [details] to obsolete.
Updated•3 years ago
|
Updated•3 years ago
|
Updated•2 years ago
|
Description
•