Cross-process navigation access-check gap: `WindowGlobalParent::RecvLoadURI/RecvInternalLoad` forwards loads without enforcing `CanAccess/CanNavigate`
Categories
(Core :: DOM: Content Processes, defect, P3)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox150 | --- | fixed |
People
(Reporter: stevenjulian1528, Assigned: aaiunusov)
References
(Blocks 1 open bug)
Details
(Keywords: ai-involved, reporter-external, sec-want, Whiteboard: [client-bounty-form][adv-main150-])
Attachments
(1 external file)
Summary
WindowGlobalParent::RecvLoadURI and RecvInternalLoad (parent process) forward cross-process navigations to a target BrowsingContext without enforcing the same access/navigation policy checks (e.g. CanAccess/CanNavigate) that exist for in-process navigation.
The parent handlers only:
- require the source and target
BrowsingContextto be in the sameBrowsingContextGroup, and - block
javascript:URLs for cross-process loads,
then directly call targetBC->LoadURI(...) / targetBC->InternalLoad(...).
This leaves a policy enforcement gap for cross-process loads initiated from a compromised content process.
Impact
A compromised content process can force navigation of other BrowsingContext instances in the same BrowsingContextGroup (including cross-origin targets), even when the attacker’s origin should not be able to control navigation of that target context.
This can be used for navigation-based security attacks such as UI redress / session confusion and as a cross-process primitive in exploit chains.
Affected code
Parent-side handlers
dom/ipc/WindowGlobalParent.cppWindowGlobalParent::RecvLoadURI(...)- checks group equality and blocks
javascript: - contains
FIXMEabout “double check CanAccess()” - forwards:
targetBC->LoadURI(aLoadState, aSetNavigating)
- checks group equality and blocks
WindowGlobalParent::RecvInternalLoad(...)- same pattern; forwards:
targetBC->InternalLoad(aLoadState)
- same pattern; forwards:
IPC entry points
dom/ipc/PContent.ipdlasync LoadURI(MaybeDiscardedBrowsingContext aContext, nsDocShellLoadState aLoadState, bool aSetNavigating) returns (bool aSuccess);async InternalLoad(nsDocShellLoadState aLoadState);
Steps to reproduce
- Put the attacker in control of a content process (renderer compromise / malicious code in content process).
- From that content process, send
PWindowGlobal::LoadURIorPWindowGlobal::InternalLoadtargeting a differentBrowsingContextin the sameBrowsingContextGroup. - Set
nsDocShellLoadStateto a cross-origin URL. - Observe the target
BrowsingContextnavigates, because the parent handler forwards the load without enforcingCanAccess/CanNavigate.
result
The parent process forwards the request after only checking:
- same
BrowsingContextGroup, and - blocking
javascript:URLs.
Suggested fix
Enforce access/navigation policy checks in the parent process before forwarding:
- Add a
CanAccess/CanNavigateequivalent check inWindowGlobalParent::RecvLoadURIandRecvInternalLoad. - Use the source
BrowsingContext/WindowGlobaland the targetBrowsingContextplus the destination URL fromnsDocShellLoadState. - Reject the IPC request when the policy check fails.
Updated•9 months ago
|
Updated•9 months ago
|
| Reporter | ||
Comment 1•9 months ago
|
||
I not sure, but this issue can be chained with bug 2008369 to create a more impactful exploit chain. While bug 2008369 allows a compromised content process to spoof a trusted principal (e.g., System Principal or bank origin) when invoking external protocols, this issue (2010310) enables that same compromised process to navigate other browsing contexts cross-origin without proper access checks.
Combined, these issues could allow navigation-based attacks under a spoofed principal context, increasing the potential for UI redress or privilege escalation.
cmiiw :D
| Assignee | ||
Updated•9 months ago
|
| Assignee | ||
Comment 2•9 months ago
•
|
||
This is a really wide problem. If a process is compromised, we can't trust it. All we can do is add principal check to the parent process (assuming it's not compromised).
nsScriptSecurityManager contains some security methods though, that can be useful:
CheckLoadURIFlags
CheckLoadURIWithPrincipal
| Assignee | ||
Comment 3•9 months ago
|
||
Updated•9 months ago
|
Comment 5•9 months ago
|
||
We don't need this hidden if we've been advertising the issue publicly in a source code comment
Updated•9 months ago
|
Updated•9 months ago
|
| Assignee | ||
Comment 6•9 months ago
|
||
implemented CanNavigate()
This is actually almost the copy of the same method from the child process
Updated•9 months ago
|
Updated•9 months ago
|
Updated•8 months ago
|
Updated•8 months ago
|
| Assignee | ||
Comment 8•8 months ago
|
||
patch is basically done
only 22 failures on treeherder
I suspect about:blank case (according to my analysis)
| Assignee | ||
Comment 9•8 months ago
|
||
basically, the following corner cases:
- about:blank
- file:// --> http:// (popups)
Updated•8 months ago
|
Updated•8 months ago
|
| Assignee | ||
Comment 10•8 months ago
|
||
all tests passed: https://phabricator.services.mozilla.com/D280216
Comment 11•8 months ago
|
||
Comment 12•8 months ago
|
||
| bugherder | ||
Updated•8 months ago
|
Updated•7 months ago
|
Updated•6 months ago
|
Description
•