Privilege escalation through devtools.inspectedWindow.eval
Categories
(WebExtensions :: Developer Tools, defect, P1)
Tracking
(firefox-esr115122+ fixed, firefox120 wontfix, firefox121 wontfix, firefox122+ fixed)
People
(Reporter: robwu, Assigned: robwu)
References
Details
(Keywords: csectype-priv-escalation, sec-moderate, Whiteboard: [adv-main122+][adv-esr115.7+])
Attachments
(5 files)
1.78 KB,
application/zip
|
Details | |
48 bytes,
text/x-phabricator-request
|
dmeehan
:
approval-mozilla-esr115+
|
Details | Review |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
dmeehan
:
approval-mozilla-esr115+
|
Details | Review |
122 bytes,
text/plain
|
Details |
devtools.inspectedWindow.eval
has denylist-based access checks (source), which are incomplete. view-source:
-URLs can be used to bypass access scheme-based restrictions, including moz-extension:
-URLs and restricted domains such as AMO.
The attached test case demonstrates the vulnerable primitive; at the end of this report I have also included a description to escalate privileges through this primitive.
STR:
- Load the attached extension (
devtools-eval.zip
) atabout:debugging
or through web-ext. It adds a panel "DevTools eval" to the devtools. This devtools panel executes code in the inspected page and prints the results. - Navigate to https://example.com/ and click on the panel's button.
- Navigate to about:debugging, click on "This Nightly" and inspect a moz-extension:-URL of another extension. Then click on the panel's button.
- View the source of the page at tab 3.
Expected:
- step 2 execution succeeds (included in the STR to show how successful execution looks like).
- step 3 execution error (other moz-extension: may be more privileged).
- step 4 execution error (other extension may be more privileged)
Actual:
- step 2 as expected.
- step 3 as expected (this was fixed in bug 1425197).
- step 4 unexpectedly succeeds, demonstrating that
devtools.inspectedWindow.eval
is able to run scripts in the context of other extensions in some cases.
Notes:
-
The
view-source:
-document has the same (storage) principal as the extension. This allows reading of other extension's content. -
At the surface, it seems that extension APIs are not injected in this context.
-
But extension APIs can be accessed indirectly, as follows:
- Install an extension that has web_accessible_resources (e.g. uBlock Origin). An alternative is to visit
about:config
, setdevtools.aboutdebugging.showHiddenAddons
to true and inspect the WebCompat add-on's manifest.json from about:debugging (after a reload). - Through the devtools, open a popup to get a handle to an extension page that has access to extension APIs:
- uBlock Origin:
w = window.open(origin + "/web_accessible_resources/README.txt")
- WebCompat:
w = window.open(origin + "/shims/mochitest-shim-1.js");
- Verify that privileged extension APIs are available (e.g. tabs API):
w.browser.tabs.getCurrent({})
- Install an extension that has web_accessible_resources (e.g. uBlock Origin). An alternative is to visit
-
The above extra notes show the extra impact on extension URLs. The same also applies to restricted domains such as AMO.
-
Access checks are deny-list-based, at https://searchfox.org/mozilla-central/rev/42acdc9cd5ae89222bdceeeaed7bacac755be48f/devtools/server/actors/addon/webextension-inspected-window.js#537-540,552,554 . An allowlist would probably make more sense here.
-
The other-extension bypass happens because the scheme is
view-source:
, which is also part ofnodePrincipal
, and thereforewindow.document.nodePrincipal.addonId
is""
.
Comment 1•1 year ago
|
||
view-source: urls are normally supposed to be same-origin with their innerURL. We'd like the right results to come out of principal comparisons rather than have everyone remember to special-case things like "view-source" -- because they won't remember, or new people won't even realize they are something they have to deal with. It sounds like a view-source principal should have an addonId
when it's a view of an extension source (and maybe some other addon-related properties).
any use of schemeIs() could be trouble and needs careful handling, and you're right that a deny-list of schemes is more dangerous than an allow-list. We do have a load flag URI_LOADABLE_BY_EXTENSIONS, but it's not used where I'd expect so maybe it's more vestigial.
Updated•1 year ago
|
Assignee | ||
Updated•1 year ago
|
Assignee | ||
Comment 3•1 year ago
|
||
and report a static error instead of including the URL in the message.
Assignee | ||
Comment 4•1 year ago
|
||
Assignee | ||
Comment 5•1 year ago
|
||
Note: the first patch fixes the issue by performing precise access checks, comparable to content scripts. It also replaces the three distinct error messages with just one static message. The original messages included the URL / origin of the tab whose access was denied. This is mostly to minimize unnecessary information exposure through extension APIs and has no significant security impact (the same information is available through other extension APIs with the right permissions).
If an external party carefully examines the patch, they may observe that the patch introduces a new check for quarantined domains. The visibility of this check is not a problem, because devtools are not included in the attacks that we are trying to defend against with the feature (introduced in bug 1834825). The extra check is primarily for consistency and future-proofing against new attacks.
I have attached the test case for view-source:
-URLs in a separate patch, in case we want to land it separately.
Assignee | ||
Comment 7•1 year ago
|
||
Adding reminder so that we don't forget to eventually land the test case (second patch) that highlights the exploitable part of this vulnerability.
Assignee | ||
Comment 8•1 year ago
|
||
The individual test ran as expected when prefs was next to the file.
But when the whole directory is selected, the test runner refuses to
run the test due to the following error:
The 'prefs' key must be set in the DEFAULT section of a manifest.
This patch fixes the issue by moving prefs to DEFAULT. This is okay
because the other test in the test manifest is independent of the pref.
Comment 10•1 year ago
|
||
Updated•1 year ago
|
Assignee | ||
Comment 11•1 year ago
|
||
Comment on attachment 9368085 [details]
Bug 1865689 - Clarify access checks in devtools.inspectedWindow.eval
ESR Uplift Approval Request
- If this is not a sec:{high,crit} bug, please state case for ESR consideration: Fixes a privilege escalation bug in extensions. Exploitation requires (1) user to install a malicious extension with the "Extend developer tools to access your data in open tabs" permission and (2) user to open the developer tools for any tab. With this, the extension can execute code in restricted documents, including other extensions and addons.mozilla.org (which should never be scriptable by any extension).
- User impact if declined: A malicious devtools extension can escalate privileges.
- Fix Landed on Version: 122
- Risk to taking this patch: Low
- Why is the change risky/not risky? (and alternatives if risky): The patch only changes behavior in the affected component, by replacing a denylist-based check with an allowlist-based check. The conditions for the allowlist are liberally chosen to allow anything conceivably acceptable, and reject accesses that we reject intentionally. All relevant scenarios are covered by unit tests.
Assignee | ||
Updated•1 year ago
|
Comment 12•11 months ago
|
||
Updated•11 months ago
|
Updated•11 months ago
|
Comment 13•11 months ago
|
||
Comment on attachment 9368085 [details]
Bug 1865689 - Clarify access checks in devtools.inspectedWindow.eval
Approved for 115.7esr.
Comment 14•11 months ago
|
||
Comment on attachment 9368424 [details]
Bug 1865689 - Fixup browser.toml - move prefs to DEFAULT
Approved for 115.7esr.
Comment 15•11 months ago
|
||
uplift |
Updated•11 months ago
|
Comment 16•11 months ago
|
||
Backed out of esr115 for causing test failures
Push: https://treeherder.mozilla.org/jobs?repo=mozilla-esr115&selectedTaskRun=L2zxQ-jSTnWw36K5RyVxDg.0&searchStr=dt1&revision=002a9e9770fe2e57c5c98f6cc213bce7a2a0a578
Example Log: https://treeherder.mozilla.org/logviewer?job_id=441570091&repo=mozilla-esr115&lineNumber=23896
:robwu could you take a look and attach a patch rebased on esr115?
Assignee | ||
Comment 17•11 months ago
|
||
The test fails because test2.example.com
cannot be loaded, and that in turn happens because http3
is enabled on the specific test configuration. I reproduced the failure locally on the ESR115 branch with:
./mach test devtools/shared/commands/inspected-window/tests/browser_webextension_inspected_window_access.js --headless --log-mach-verbose --use-http3-server
The required registration for test2.example.com
(*.example.com
) was added in https://hg.mozilla.org/mozilla-central/rev/1f68fb3f63169376727ad402c5b34eb2c8efdec1 , which landed in 116.
I recommend to uplift https://hg.mozilla.org/mozilla-central/rev/1f68fb3f6316 - I don't expect any regressions because this merely adds a few extra domains; hosts that previously did not resolve with --use-http3-server
will load as expected. Once this sticks, the two patches above can be relanded without changes.
Alternatively, reland with skip-if = http3
added below [browser_webextension_inspected_window_access.js]
. For simplicity, consider squashing both patches together (and only retain the first commit message) and then add skip-if
.
Updated•11 months ago
|
Updated•11 months ago
|
Comment 18•10 months ago
|
||
Comment on attachment 9368085 [details]
Bug 1865689 - Clarify access checks in devtools.inspectedWindow.eval
Approved for 115.7esr.
Comment 19•10 months ago
|
||
Comment on attachment 9368424 [details]
Bug 1865689 - Fixup browser.toml - move prefs to DEFAULT
Approved for 115.7esr.
Comment 20•10 months ago
|
||
uplift |
Updated•10 months ago
|
Updated•10 months ago
|
Updated•10 months ago
|
Comment 21•10 months ago
|
||
Updated•10 months ago
|
Comment 22•6 months ago
|
||
Making Firefox 122 security bugs public. [bugspam filter string: Pilgarlic-Towers]
Updated•6 months ago
|
Assignee | ||
Comment 23•6 months ago
|
||
I'll land the test now since the bug has become public.
Comment 24•6 months ago
|
||
Comment 25•6 months ago
|
||
bugherder |
Description
•