Closed Bug 2032297 Opened 7 months ago Closed 7 months ago

RecvPBroadcastChannelConstructor async principal check only verifies internal consistency of two attacker-controlled values — compromised renderer joins any origin's BroadcastChannel

Categories

(Core :: DOM: postMessage, defect)

defect

Tracking

()

RESOLVED DUPLICATE of bug 2016925

People

(Reporter: pakhunov.anton.n, Unassigned)

Details

(Keywords: ai-involved, reporter-external)

While auditing PBackground actor constructors I found that RecvPBroadcastChannelConstructor (ipc/glue/BackgroundParentImpl.cpp ~line 789) dispatches an async CheckPrincipalRunnable to validate the caller, but the check only verifies that the IPC-supplied aPrincipalInfo and aOrigin are internally consistent with each other. Since the attacker controls both, a consistent pair for any target origin trivially passes.

The actor is registered in the shared BroadcastChannelService singleton in its constructor — before the async check fires:

// AllocPBroadcastChannelParent — actor registered immediately with attacker-controlled origin key
BackgroundParentImpl::AllocPBroadcastChannelParent(
    const PrincipalInfo& aPrincipalInfo, const nsACString& aOrigin, ...) {
  nsString originChannelKey;
  originChannelKey.Assign(aChannel);
  originChannelKey.AppendLiteral("|");
  originChannelKey.Append(NS_ConvertUTF8toUTF16(aOrigin));  // attacker-controlled
  return new BroadcastChannelParent(originChannelKey);       // registers in BroadcastChannelService
}

// RecvPBroadcastChannelConstructor — async check only checks consistency of two IPC values
mozilla::ipc::IPCResult BackgroundParentImpl::RecvPBroadcastChannelConstructor(
    PBroadcastChannelParent* actor, const PrincipalInfo& aPrincipalInfo,
    const nsACString& aOrigin, ...) {
  // ...
  RefPtr<CheckPrincipalRunnable> runnable =
      new CheckPrincipalRunnable(parent.forget(), aPrincipalInfo, aOrigin);
  MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
  return IPC_OK();  // actor is already live in mAgents
}

CheckPrincipalRunnable::Run() (lines 751-778):

auto principalOrErr = PrincipalInfoToPrincipal(mPrincipalInfo);  // from IPC
// ...
principalOrErr.unwrap()->GetOrigin(origin);  // derived from IPC spec
if (NS_WARN_IF(!mOrigin.Equals(origin))) {   // mOrigin also from IPC
    contentParent->KillHard(...);
}
// If attacker sends consistent pair (spec="https://bank.com/", aOrigin="https://bank.com") -> PASSES

BroadcastChannelService is a process-level singleton with a single mAgents hashmap shared across all content process connections. Once registered, the malicious actor receives every PostMessage call for the claimed origin+channel key.

Attack (compromised evil.com renderer targeting bank.com):

  1. Send PBroadcastChannelConstructor with:
    aPrincipalInfo = ContentPrincipalInfo{ spec: "https://bank.com/", originNoSuffix: "https://bank.com", attrs: {} }
    aOrigin = "https://bank.com"
    aChannel = "sessionSync" (known or guessed)
  2. AllocPBroadcastChannelParent registers actor under key "sessionSync|https://bank.com" in mAgents.
  3. CheckPrincipalRunnable: GetOrigin(principal) == "https://bank.com" == mOrigin -> PASSES, process not killed.
  4. Malicious actor permanently receives all BroadcastChannel("sessionSync") messages from bank.com tabs.
  5. Can also inject messages: all bank.com tabs receive them as same-origin.

Impact: cross-origin BroadcastChannel eavesdropping and message spoofing, breaking site isolation. Requires compromised renderer.

The fix is to call ContentParent::ValidatePrincipal (ValidatePrincipalCouldPotentiallyBeLoadedBy) on the IPC-supplied principal — as done for clipboard, notifications, and initial window initialization — either synchronously in RecvPBroadcastChannelConstructor or by deferring RegisterActor until the authorization check completes.

Firefox version: mozilla-central (trunk)
OS: all platforms

Group: core-security → dom-core-security
Status: UNCONFIRMED → RESOLVED
Closed: 7 months ago
Component: DOM: Workers → DOM: postMessage
Duplicate of bug: 2016925
Resolution: --- → DUPLICATE
Group: dom-core-security
You need to log in before you can comment on or make changes to this bug.