Closed Bug 2077356 Opened 1 month ago Closed 1 month ago

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)

defect

Tracking

()

RESOLVED DUPLICATE of bug 2043810

People

(Reporter: d7meealz, Unassigned)

Details

(Keywords: reporter-external, Whiteboard: [client-bounty-form])

Attachments

(1 file)

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-1593
    already_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:

  1. Pass the top-context id of a different tab/browsing context to obtain its
    BackgroundSessionStorageManager, then
  2. Open a cache for a victim origin's PrincipalInfo/OriginKey and
  3. RecvLoad returns that origin's sessionStorage contents (cross-origin data disclosure), and
    RecvCheckpoint writes 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).

Flags: sec-bounty?

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.

Group: firefox-core-security → dom-core-security
Status: UNCONFIRMED → RESOLVED
Closed: 1 month ago
Component: Security → Storage: localStorage & sessionStorage
Duplicate of bug: 2043810
Product: Firefox → Core
Resolution: --- → DUPLICATE
Group: dom-core-security
Flags: sec-bounty? → sec-bounty-
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: