Use-After-Free in BoundStorageKeyParent via Dangling PBackgroundParent Pointer
Categories
(Core :: Storage: Cache API, defect)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox-esr115 | --- | unaffected |
| firefox-esr140 | --- | unaffected |
| firefox147 | --- | wontfix |
| firefox148 | + | fixed |
| firefox149 | + | fixed |
| firefox150 | + | fixed |
People
(Reporter: jkratzer, Assigned: hsingh)
References
(Regression)
Details
(5 keywords, Whiteboard: [adv-main148.0.2+r])
Attachments
(3 files, 3 external files)
Use-After-Free in BoundStorageKeyParent via Dangling PBackgroundParent Pointer
Vulnerability Type
Heap Use-After-Free (CWE-416)
Bug Class
Use-after-free via dangling raw pointer across independent IPC actor lifetimes
Affected Component
dom/cache/BoundStorageKeyParent.h(line 46: rawMOZ_NON_OWNING_REFpointer)dom/cache/BoundStorageKeyParent.cpp(line 23: use of dangling pointer)dom/cache/CacheStorageParent.cpp(line 50: dereference of freed memory)ipc/glue/BackgroundParentImpl.cpp(line 1113: creation of BoundStorageKeyParent with rawthispointer)
Summary
BoundStorageKeyParent stores a raw, non-owning pointer (MOZ_NON_OWNING_REF) to PBackgroundParent (line 46 of BoundStorageKeyParent.h). Since PBoundStorageKey is a top-level protocol with its own independent IPC transport (created via Endpoint), its lifetime is completely decoupled from PBackground. A compromised content process can destroy the PBackground connection while keeping the PBoundStorageKey channel alive, then send a PCacheStorage constructor message which causes the parent to dereference the freed PBackgroundParent memory.
Detailed Analysis
Root Cause
In BackgroundParentImpl::RecvCreateBoundStorageKeyParent (BackgroundParentImpl.cpp:1113):
auto* pActor = new dom::cache::BoundStorageKeyParent(this);
The this pointer (which is the BackgroundParentImpl* / PBackgroundParent*) is stored as a raw pointer in BoundStorageKeyParent::mBackgroundParent (BoundStorageKeyParent.h:46):
mozilla::ipc::PBackgroundParent* MOZ_NON_OWNING_REF mBackgroundParent;
The comment on the raw pointer incorrectly states:
"Raw ptr is fine here as PBackground is one of the few top-level that gets created very early on in the content and parent lifecycle and extends the lifetime of this class."
This assumption is wrong because PBoundStorageKey is a top-level protocol with its own independent transport channel, so IPDL provides no lifetime guarantee between PBackground and PBoundStorageKey.
Exploitation Path
- Content process creates PBackground — standard initialization
- Content process sends
CreateBoundStorageKeyParent— parent createsBoundStorageKeyParentholding raw ptr toPBackgroundParent - Content process closes PBackground —
PBackgroundParentis destroyed and freed - Content process sends
PCacheStorageon PBoundStorageKey — parent callsBoundStorageKeyParent::AllocPCacheStorageParent()which passes the danglingmBackgroundParenttoCacheStorageParentconstructor andPrincipalVerifier::CreateAndDispatch() - Parent dereferences freed memory —
BackgroundParent::GetContentParentHandle(mBackgroundParent)reads from freed heap, causing heap-use-after-free
ASAN Stack Trace (Crash Point)
READ of size 8 at freed memory (thread T11 - background thread)
#0 RefPtr<ThreadsafeContentParentHandle>::get()
#1 ParentImpl::GetContentParentHandle(PBackgroundParent*) BackgroundImpl.cpp:783
#2 BackgroundParent::GetContentParentHandle(PBackgroundParent*) BackgroundImpl.cpp:683
#3 PrincipalVerifier::PrincipalVerifier(...) PrincipalVerifier.cpp:63
#4 PrincipalVerifier::CreateAndDispatch(...) PrincipalVerifier.cpp:41
#5 CacheStorageParent::CacheStorageParent(PBackgroundParent*,...) CacheStorageParent.cpp:50
#6 AllocPCacheStorageParent(PBackgroundParent*,...) CacheStorageParent.cpp:31
#7 BoundStorageKeyParent::AllocPCacheStorageParent(...) BoundStorageKeyParent.cpp:23
Exploitability
This is a heap-use-after-free where:
- The freed object is a 680-byte
ParentImpl(PBackgroundParent implementation) - The read occurs at offset 648 within the freed object
- The freed memory can be reallocated with attacker-controlled content via heap spray
- An attacker can control what data is read from the freed memory, potentially:
- Hijacking the
ThreadsafeContentParentHandleRefPtr to point to attacker-controlled memory - Gaining control of subsequent operations that use the returned handle
- Escalating to arbitrary code execution in the parent process
- Hijacking the
Proof of Concept
The exploit modifies the content process to:
- Obtain the PBackground child actor
- Create
PBoundStorageKeyendpoints and sendCreateBoundStorageKeyParentto parent - Bind the child endpoint locally
- Call
Close()on PBackground, destroyingPBackgroundParentin the parent process - After a delay, send
PCacheStorageconstructor on thePBoundStorageKeychannel - Parent-side
BoundStorageKeyParent::AllocPCacheStorageParent()dereferences the freedmBackgroundParent
Recommended Fix
Replace the raw MOZ_NON_OWNING_REF pointer with a RefPtr or WeakPtr, and add a null-check before use:
// In BoundStorageKeyParent.h:
// Replace:
// mozilla::ipc::PBackgroundParent* MOZ_NON_OWNING_REF mBackgroundParent;
// With:
// RefPtr<mozilla::ipc::PBackgroundParent> mBackgroundParent;
// Or use a weak reference with null-check in AllocPCacheStorageParent()
Alternatively, clear mBackgroundParent when PBackground is destroyed by registering BoundStorageKeyParent as a destruction observer, or by making PBoundStorageKey a managed sub-protocol of PBackground so IPDL enforces proper lifetime ordering.%
| Reporter | ||
Comment 1•9 months ago
|
||
| Reporter | ||
Comment 2•9 months ago
|
||
| Reporter | ||
Comment 3•9 months ago
|
||
| Reporter | ||
Updated•9 months ago
|
| Reporter | ||
Updated•9 months ago
|
Comment 4•9 months ago
|
||
Triage owner doesn't have access to the bug. CCing jld.
This file hasn't been touched in a while, but most recently by Nika. CCing her as well.
Updated•9 months ago
|
Updated•9 months ago
|
Updated•9 months ago
|
Comment 6•9 months ago
|
||
From skimming the code, I suspect that this dates to the landing of BoundStorageKeyParent in bug 1969120, which would mean neither ESR is affected, but it would be good to have confirmation.
| Assignee | ||
Updated•9 months ago
|
| Assignee | ||
Comment 7•9 months ago
|
||
Yes, the effected code and file in question were not introduced a long ago. I have assigned the task to myself and will be working on it very shortly.
Updated•9 months ago
|
Comment 8•9 months ago
|
||
Set release status flags based on info from the regressing bug 1969120
Updated•9 months ago
|
| Assignee | ||
Comment 9•8 months ago
|
||
Comment 10•8 months ago
|
||
Set release status flags based on info from the regressing bug 1969120
Comment 11•8 months ago
|
||
Harveer, the planned Fx148 dot release builds and releases next week.
This would need to land and have beta/release uplift requests this week to be included.
| Assignee | ||
Comment 12•8 months ago
|
||
sure, I will ping reviewers to expedite the review process.
Comment 13•8 months ago
|
||
Comment 14•8 months ago
|
||
This should have gotten a sec-approval flag before landing. Please fill it out even though it is kind of too late already. Thanks.
Comment 15•8 months ago
|
||
Sorry if my message in Comment 11 implied otherwise, but as mentioned in Comment 14 and in a message when landing the bug, it needs sec approval
| Assignee | ||
Comment 16•8 months ago
|
||
oh apologies. I thought sec-appovals are only needed when uplifting the patches and not for landing to main. I will try to do that now.
| Assignee | ||
Comment 17•8 months ago
|
||
Comment on attachment 9547647 [details]
(secure)
Security Approval Request
- How easily could an exploit be constructed based on the patch?: It's not easy to exploit this bug as it assumes compromised content process.
- 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?: ESRs are not effected but beta and release. Yes, it's marked as a regression accordingly
- 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?: It should be pretty trivial to cherry-pick the changes
- How likely is this patch to cause regressions; how much testing does it need?: Existing automated regression tests should cover the new changes
- Is the patch ready to land after security approval is given?: Yes
- Is Android affected?: Unknown
| Assignee | ||
Updated•8 months ago
|
Comment 18•8 months ago
|
||
Comment 19•8 months ago
|
||
The patch landed in nightly and beta is affected.
:hsingh, is this bug important enough to require an uplift?
- If yes, please nominate the patch for beta approval.
- See https://wiki.mozilla.org/Release_Management/Requesting_an_Uplift for documentation on how to request an uplift.
- If no, please set
status-firefox149towontfix.
For more information, please visit BugBot documentation.
| Assignee | ||
Comment 20•8 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D284722
Updated•8 months ago
|
Comment 21•8 months ago
|
||
firefox-beta Uplift Approval Request
- User impact if declined: Parent process could lead to crash in case content process gets compromised. The related bug is rated as sec-high.
- Code covered by automated testing: yes
- Fix verified in Nightly: yes
- Needs manual QE test: yes
- Steps to reproduce for manual QE testing: There's STR on the bug. It involves assuming compromised content process.
- Risk associated with taking this patch: low
- Explanation of risk level: Patch should apply cleanly and should be covered by existing regression tests.
- String changes made/needed: N/A
- Is Android affected?: no
Comment 22•8 months ago
|
||
firefox-release Uplift Approval Request
- User impact if declined: Parent process could lead to crash in case content process gets compromised. The related bug is rated as sec-high.
- Code covered by automated testing: yes
- Fix verified in Nightly: yes
- Needs manual QE test: yes
- Steps to reproduce for manual QE testing: There's STR on the bug. It involves assuming compromised content process.
- Risk associated with taking this patch: low
- Explanation of risk level: Patch should apply cleanly and should be covered by existing regression tests.
- String changes made/needed: N/A
- Is Android affected?: no
| Assignee | ||
Comment 23•8 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D284722
| Assignee | ||
Updated•8 months ago
|
Comment 24•8 months ago
|
||
We noticed that the "qe-verify+" label was added. Can this issue be verified manually? If so, could you please provide specific steps for manual verification?”
Comment 25•8 months ago
|
||
This issue cannot be verified without creating your own Firefox build, so likely not something QA can easily verify as fixed.
Comment 26•8 months ago
|
||
Comment on attachment 9547647 [details]
(secure)
sec-approval+ to land now and request uplifts
Updated•8 months ago
|
Updated•8 months ago
|
Comment 27•8 months ago
|
||
| uplift | ||
Updated•8 months ago
|
Updated•8 months ago
|
Comment 28•8 months ago
|
||
| uplift | ||
Updated•8 months ago
|
Updated•5 months ago
|
Description
•