Compromised content process can read/write any extension's storage.local via content_parent context spoofing in recvCreateProxyContext (code execution demonstrated via Violentmonkey)
Categories
(WebExtensions :: General, defect)
Tracking
(Not tracked)
People
(Reporter: kerberoasting, Unassigned)
References
Details
(Keywords: csectype-priv-escalation, reporter-external, sec-moderate, Whiteboard: [client-bounty-form])
Attachments
(1 file)
|
21.28 KB,
application/x-zip-compressed
|
Details |
Hey there. I'm aware of bug 1750422. This report demonstrates a distinct entry point (recvCreateProxyContext) with escalated impact (arbitrary code execution via storage.local + runtime.reload), which may not be addressed by the existing planned patch.
recvCreateProxyContext() checks sender.verified for addon_parent (line 1058 on nightly) but not for content_parent (line 1093). A compromised content process can create a spoofed content_parent ProxyContext for any installed extension, giving full read/write to storage.local and access to runtime.reload.
Impact:
- Code execution via Violentmonkey: write malicious userscript to storage + runtime.reload = JS on every page
- Vault exfiltration via Bitwarden: 42 storage keys including master key hash, encrypted vault, refresh token
- Server-side account takeover: stolen refresh token exchanged for new access token, full vault sync from Bitwarden API (standalone, no Firefox)
- Destructive write: local vault ciphers wiped via IPC
Tested on Firefox ESR 140.7.0.
How was this issue discovered?
Auditing recvCreateProxyContext() for sender verification gaps. Found addon_parent checks sender.verified but content_parent does not. Built PoCs with Marionette system sandbox (compromised renderer simulation per Mozilla threat model). Confirmed storage read/write, runtime.reload, and code execution end-to-end.
See attached zip for full PoCs and MD fie.
Updated•1 month ago
|
Comment 1•1 month ago
|
||
I think this might be a sec-high privilege escalation, but I'm not 100% sold this counts as a sandbox escape as it does not provide the privileges of the unsandboxed parent process. The UXSS aspect seems to hinge on a specific extension.
I think it would be more convincing if you could abuse a built-in extension (eg web compat shims).
| Reporter | ||
Comment 2•1 month ago
|
||
Hey there. Built-in extensions (I tested a few like formautofill) use a different storage registration path and all failed, thus only third-party webextensions are vulnerable. The vulnerability itself is the missing sender.verified check on content_parent (line 1093) that addon_parent already has (line 1058), allowing a compromised content process to read/write any third-party extension's storage.local. This was demonstrated end-to-end with Bitwarden vault exfiltration + standalone API account takeover via stolen refresh token, and arbitrary code execution via Violentmonkey script injection due to the extensions behavior.
I agree this is not a sandbox escape. However, the real-world impact is relatively high because many users have at least one high-value 3rd party extension installed (cred theft, ATO, code exec). Thanks! - Richard
Comment 3•1 month ago
|
||
Given that it requires a non-default configuration it's closer to sec-moderate according to our severity guidelines
Comment 4•1 month ago
|
||
The primary claim is that "content_parent does NOT check sender.verified" and that exploitation can be demonstrated through the storage.local API. While the demo demonstrates an issue, those reflect implementation issues in extensions, not in Firefox.
In the bugzilla_report_ext_storage.md file in your zip file, you are claiming that a sender.verified check is missing for content_parent. If we were to add a sender.verified check as you suggested, then all extension API calls from content scripts would break... The sender.verified flag is derived from verifyEnv, which only provides verification that the caller is a trusted extension process (and we check sender.verified to reject attempts to create a privileged extension context for unverified processes). Other processes (including content processes along with content_parent) are considered unverified.
We only expose a limited number of APIs to content scripts, documented at https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#webextension_apis
This list includes the storage.local API ("Values (...) are available to all scripts in the background context and content scripts"), so extensions cannot have an expectation of the data being isolated from hostile websites (if the content process were to be compromised). There is an API proposal (storage.setAccessLevel - bug 1724754) to hide the storage data from content scripts, but that would still require an opt-in from extensions. Even without this API, extensions today can also use storage APIs tied to their origin (e.g. IndexedDB) to store data in a way isolated from the content scripts.
Your sample of victim extensions are password managers and user script managers. These extensions typically declare content scripts to run on all websites, so even if we wanted to, we could not feasibly reject forged messages from content scripts for these API calls, because a legitimate API call would have the same IPC message.
| Reporter | ||
Comment 5•1 month ago
|
||
I agree that it's in between the two and not clearcut. One clarification though, the vulnerability itself (the missing sender.verified check on content_parent) is in default Firefox code and requires no non-default configuration to reach. A compromised content process can hit the vulnerable code path on any Firefox install regardless of settings. What's conditional is the impact which depends on which third-party extensions the user has installed, and built-in extensions aren't affected, so I understand why it feels closer to moderate.
| Reporter | ||
Comment 6•1 month ago
|
||
ahh. i just read your response, that makes complete sense. thanks for the info.
Updated•1 month ago
|
Description
•