Closed Bug 2045532 Opened 5 months ago Closed 5 months ago

Missing sender remote-type check in PBroadcastChannel Constructor breaks origin isolation

Categories

(Core :: DOM: Workers, defect)

defect

Tracking

()

RESOLVED DUPLICATE of bug 2016925

People

(Reporter: atsu120225, Unassigned)

Details

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

Attachments

(1 file)

Attached patch patch.patch — — Splinter Review

BackgroundParentImpl::RecvPBroadcastChannelConstructor only checks that the supplied PrincipalInfo and aOrigin string agree.
It never calls ValidatePrincipalCouldPotentiallyBeLoadedBy(principal, remoteType) against the sender content process, so a compromised child registers a BroadcastChannelParent against <channel>|<victim-origin+OA> for any principal the legacy check happens to accept.

The actor then participates in BroadcastChannelService::PostMessage
fan-out in both directions

  • Receive. Every other process broadcasting on the victim agent key feeds its SharedMessageBody to the attacker child via SendNotify. The blob is structured-clone data carrying whatever the victim site puts on the channel: auth tokens, session ids, partitioned cookie state, paywall content, real-time RPC payloads.
  • Send. Attacker calls PostMessage. Each victim receiver in BroadcastChannel::MessageReceived builds a MessageEvent with mOrigin = mOriginForEvents and SetTrusted(true). The victim cannot tell attacker traffic from its own same-origin broadcast.

What's reachable without depending on the victim site's JS

  • Container isolation bypass. The agent key includes userContextId. Forging OriginAttributes{userContextId=N} from a process in container M joins container N's BC traffic.
  • Private-browsing isolation bypass. Same mechanism with privateBrowsingId=1 from a normal-mode process.
  • Storage-partitioning bypass. Forge partitionKey to a partitioned third-party context.
  • Cross-extension hijack. ValidatePrincipalCouldPotentiallyBeLoadedBy unconditionally returns true for moz-extension:// , so forging moz-extension://<EXT_UUID> joins that extension's BC even after this patch lands. Any extension that uses BroadcastChannel for command dispatch executes attacker data with its full API surface.
  • SystemPrincipal reach. Pre-patch, SystemPrincipalInfo passes the origin-equality check. No shipped chrome JS subscribes to BC today, so this is defense-in-depth, but the trust gap currently exists.

Receivers that turn the injection into UXSS: every site using BroadcastChannel for cross-tab sync, including Workbox's SKIP_WAITING / CLIENTS_CLAIM protocol used by Workbox-built PWAs and NextAuth.js's nextauth.message channel. CSP script-src 'self' does not block the chain because the executing code is the victim's own.

Not the same as Bug 1318387 ("BroadcastChannel should wait until the security checks are completed", 2016, NEW after backout). That bug is about the race window between actor allocation and the check completing. This one is about the check itself never validating the sender remote type, which would still hold even if the race were closed.

Patch replaces the main-thread runnable with a synchronous PBackground check: PrincipalInfoToPrincipal → ValidatePrincipalCouldPotentiallyBeLoadedBy(principal, parent->GetRemoteType()) → origin equality. Mismatch returns IPC_FAIL. Dead CheckPrincipalRunnable removed. ./mach build ipc/glue clean, 0 warnings.

Flags: sec-bounty?

Dupe of bug 2016925?

Group: firefox-core-security → dom-core-security
Component: Security → DOM: Workers
Product: Firefox → Core

(In reply to :Gijs (he/him) from comment #1)

Dupe of bug 2016925?

Yes, thanks.

Status: UNCONFIRMED → RESOLVED
Closed: 5 months ago
Duplicate of bug: 2016925
Resolution: --- → DUPLICATE
Flags: sec-bounty? → sec-bounty-
Group: dom-core-security
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: