PBackgroundSessionStorageManagerParent trusts a content-supplied top-context id and principal — a compromised content process can read/write another origin's sessionStorage
Categories
(Core :: Storage: localStorage & sessionStorage, defect)
Tracking
()
People
(Reporter: d7meealz, Unassigned)
Details
(Keywords: reporter-external, Whiteboard: [client-bounty-form])
Attachments
(1 file)
|
6.40 KB,
text/plain
|
Details |
SessionStorageManagerParent is allocated from PBackground with a caller-supplied top-level
context id, and the per-origin cache actor is allocated with a caller-supplied PrincipalInfo +
OriginKey. Neither is validated against the sending content process, and the parent uses them
directly to select the backing BackgroundSessionStorageManager and storage area.
Root cause (mozilla-central tip 2026-10-01, 1756a6ab15916c9f17ab5c59fd35c9ee925bc644):
- Content side sends
mBrowsingContext->Top()->Id():
dom/storage/SessionStorageManager.cpp:351
backgroundActor->SendPBackgroundSessionStorageManagerConstructor(actor, mBrowsingContext->Top()->Id()); - Parent allocation performs no sender/ownership check:
dom/storage/StorageIPC.cpp:1591-1593already_AddRefed<PBackgroundSessionStorageManagerParent> AllocPBackgroundSessionStorageManagerParent(const uint64_t& aTopContextId) { return MakeAndAddRef<SessionStorageManagerParent>(aTopContextId); } - The constructor keys the global manager by that id:
dom/storage/StorageIPC.cpp:1420-1423
SessionStorageManagerParent::SessionStorageManagerParent(uint64_t aTopContextId) : mBackgroundManager(BackgroundSessionStorageManager::GetOrCreate(aTopContextId)) - The cache actor then accepts a content-supplied principal key and origin key:
dom/storage/StorageIPC.cpp:1441(AllocPBackgroundSessionStorageCacheParent(aPrincipalInfo, aOriginKey))
and:1365-1400(RecvLoad->manager->CopyDataToContentProcess(originAttrs, mOriginKey, *aData),
RecvCheckpoint->manager->UpdateData(originAttrs, mOriginKey, aWriteInfos)).
Compare the LSNG (localStorage) path, which calls VerifyPrincipalInfo/VerifyOriginKey before using
caller-supplied values; the sessionStorage path has no equivalent.
Impact
A compromised content process (the model in which arbitrary content-process IPC calls are allowed; the
program's footnote 0 treats these as Highest Impact if they reach a privileged action) can:
- Pass the top-context id of a different tab/browsing context to obtain its
BackgroundSessionStorageManager, then - Open a cache for a victim origin's
PrincipalInfo/OriginKeyand RecvLoadreturns that origin's sessionStorage contents (cross-origin data disclosure), and
RecvCheckpointwrites attacker-controlled key/value pairs into it (integrity violation).
sessionStorage is origin-scoped and same-process-scoped by design; this defeats the origin boundary.
Suggested test case
From the parent-side chrome context of a build with a second top-level content tab (origin B), hook the
PBackgroundSessionStorageManagerParent allocation to record aTopContextId/PrincipalInfo, then have a
compromised-content-process test (or a direct PBackground message) construct a manager for the other
tab's top id plus a cache for B's principal, and verify RecvLoad returns B's data. (If a simpler
verification is preferred: add a temporary MOZ_DIAGNOSTIC_ASSERT that aTopContextId belongs to the
calling ContentParent and run the existing session storage tests — the assertion fires for the
legitimate same-process case only, demonstrating the missing ownership link.)
Suggested fix
Validate that the aTopContextId belongs to the calling content process (e.g. a WindowContext-to-
ContentParent ownership check analogous to CanonicalBrowsingContext::IsOwnedByProcess), and derive
the cache PrincipalInfo/OriginKey from the sender rather than trusting the message (or call the LSNG
VerifyPrincipalInfo/VerifyOriginKey helpers).
Comment 1•1 month ago
|
||
Automatic triage (under development): deduplication
No validation or verification has been performed.
This issue has been determined to be a duplicate of bug 2043810.
Both bugs report that a compromised content process can create a PBackgroundSessionStorageManager for another tab's top-level context id and then a PBackgroundSessionStorageCache with a forged PrincipalInfo and originKey. The parent never validates these against the sending process, so another origin's sessionStorage can be read through SessionStorageCacheParent::RecvLoad. The fix needed is the same: validate the cache principal and originKey against the sender.
Updated•23 days ago
|
Description
•