Closed Bug 2016925 Opened 9 months ago Closed 4 months ago

PBroadcastChannel: Self-referential CheckPrincipalRunnable allows cross-origin message injection via forged PrincipalInfo

Categories

(Core :: DOM: postMessage, defect, P3)

defect

Tracking

()

RESOLVED FIXED
154 Branch
Tracking Status
firefox-esr115 --- wontfix
firefox-esr140 --- wontfix
firefox152 --- wontfix
firefox153 --- fixed
firefox154 --- fixed

People

(Reporter: kerberoasting, Assigned: nika)

References

(Blocks 1 open bug)

Details

(Keywords: csectype-site-isolation, reporter-external, sec-want, Whiteboard: [client-bounty-form])

Attachments

(1 file)

BroadcastChannel (managed by PBackground) has a self-referential principal validation. CheckPrincipalRunnable (BackgroundParentImpl.cpp ~line 1230) only checks that the child-supplied PrincipalInfo deserializes to the same origin as the child-supplied origin string. Both values come from the same untrusted content process — a compromised process sends consistent values and the check always passes. No ValidatePrincipal, AssertProcessPrincipal, or ContentProcessHasPrincipal is called.

The XXX comment at ~line 1295 acknowledges: "The principal can be checked right here on the PBackground thread since BackgroundParentImpl now overrides the ProcessingError method and kills invalid child processes." Yet the actual check remains self-referential.

BroadcastChannelParent's constructor calls RegisterActor() immediately (line 21, dom/broadcastchannel/BroadcastChannelParent.cpp), before CheckPrincipalRunnable is dispatched async to the main thread. The actor is fully operational before any validation runs.

RecvPostMessage (line 33) has zero validation — forwards to BroadcastChannelService::PostMessage which routes by originChannelKey derived from child-supplied PrincipalInfo. A forged principal produces the same routing key as legitimate actors.

Impact: A compromised content process joins any origin's BroadcastChannel, reads session tokens / CSRF tokens / state sync messages, and injects arbitrary messages. PoC demonstrates full attack chain: intercept session tokens, inject fake "session expired", capture re-entered credentials.

Suggested fix: replace self-referential CheckPrincipalRunnable with ValidatePrincipal / ContentProcessHasPrincipal that cross-references the child process's actual site assignment.

Attached: write-up (submission_final.md) and Marionette PoC (test_broadcastchannel.py) demonstrating the full attack chain on Firefox ESR 140.7.0.

=== How discovered ===
Static source code analysis of dom/broadcastchannel/BroadcastChannelParent.cpp, ipc/glue/BackgroundParentImpl.cpp (CheckPrincipalRunnable, RecvPBroadcastChannelConstructor).

=== Attachments ===

  1. test_broadcastchannel.py (5-phase Marionette PoC)

=== PoC prerequisites ===
pip install marionette_driver
Firefox ESR (tested on 140.7.0): apt install firefox-esr
Run: python3 test_broadcastchannel.py

Flags: sec-bounty?
Group: firefox-core-security → dom-core-security
Component: Security → IPC
Product: Firefox → Core
Component: IPC → DOM: postMessage

This is something that would be nice to have, but we don't really attempt to enforce anywhere.

Keywords: sec-want
Severity: -- → S3
Priority: -- → P3
Duplicate of this bug: 2023074
Duplicate of this bug: 2026011
Duplicate of this bug: 2027089
No longer duplicate of this bug: 2027089
Duplicate of this bug: 2031619
Duplicate of this bug: 2032297
Duplicate of this bug: 2034493
Duplicate of this bug: 2034878
Duplicate of this bug: 2038523
Duplicate of this bug: 2040230
Duplicate of this bug: 2045532
Duplicate of this bug: 2050674

Yes, this was fixed by bug 2039990 and the next step is bug 1853706 such that the storage key is just inherent from the managing actor. From discussion with :mccr8 I'm just marking bugs like this as dependent on that bug and fixed since those structural changes were not done as a security bug and duping to it I think will create edges that bugzilla does not hide? (I am open to other tracking approaches.)

Status: UNCONFIRMED → RESOLVED
Closed: 4 months ago
Resolution: --- → FIXED
Group: dom-core-security → core-security-release
Assignee: nobody → nika
Target Milestone: --- → 154 Branch
QA Whiteboard: [sec] [qa-triage-done-c154/b153]
Flags: sec-bounty? → sec-bounty-
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: