Missing sender remote-type check in PBroadcastChannel Constructor breaks origin isolation
Categories
(Core :: DOM: Workers, defect)
Tracking
()
People
(Reporter: atsu120225, Unassigned)
Details
(Keywords: reporter-external, Whiteboard: [client-bounty-form])
Attachments
(1 file)
|
3.68 KB,
patch
|
Details | Diff | 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
SharedMessageBodyto the attacker child viaSendNotify. 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 inBroadcastChannel::MessageReceivedbuilds aMessageEventwithmOrigin = mOriginForEventsandSetTrusted(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. ForgingOriginAttributes{userContextId=N}from a process in container M joins container N's BC traffic. - Private-browsing isolation bypass. Same mechanism with
privateBrowsingId=1from a normal-mode process. - Storage-partitioning bypass. Forge
partitionKeyto a partitioned third-party context. - Cross-extension hijack.
ValidatePrincipalCouldPotentiallyBeLoadedByunconditionally returns true formoz-extension://, so forgingmoz-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,
SystemPrincipalInfopasses 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.
Comment 1•5 months ago
|
||
Dupe of bug 2016925?
Comment 2•5 months ago
|
||
Updated•5 months ago
|
Updated•1 month ago
|
Description
•