CVE-2025-3070
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
TEST_Fextensions/browser/api/content_settings/content_settings_store_unittest.cc |
modified |
Files Changed
extensions/browser/api/content_settings/content_settings_store.ccextensions/browser/api/content_settings/content_settings_store_unittest.ccextensions/test/DEPSextensions/test/extensions_unittests_main.cctools/metrics/histograms/metadata/extensions/histograms.xml
Patch
From 34a2937e30659b6d5616d881f3be0f93b4a59c47 Mon Sep 17 00:00:00 2001 From: Emily Stark <[email protected]> Date: Thu, 29 Aug 2024 04:11:21 +0000 Subject: [PATCH] Add metrics for chrome.contentSettings extension usage This CL adds metrics for how often chrome-extension:// origins are used to set content settings via the chrome.contentSettings API, to see if this can be deprecated. Bug: 40086360 Change-Id: Ide2b22a6e628fd8bebbd227032e5e4c7264c1c1d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5814282 Reviewed-by: Balazs Engedy <[email protected]> Reviewed-by: Devlin Cronin <[email protected]> Reviewed-by: Kelvin Jiang <[email protected]> Commit-Queue: Emily Stark <[email protected]> Cr-Commit-Position: refs/heads/main@{#1348438} --- diff --git a/extensions/browser/api/content_settings/content_settings_store.cc b/extensions/browser/api/content_settings/content_settings_store.cc index 9a038a3..62a0ac0 100644 --- a/extensions/browser/api/content_settings/content_settings_store.cc +++ b/extensions/browser/api/content_settings/content_settings_store.cc @@ -147,6 +147,18 @@ ContentSettingsType type, ContentSetting setting, ChromeSettingScope scope) { + if (primary_pattern.GetScheme() == + ContentSettingsPattern::SCHEME_CHROMEEXTENSION) { + content_settings_uma_util::RecordContentSettingsHistogram( + "Extensions.ContentSettings.PrimaryPatternChromeExtensionScheme", type); + } + if (secondary_pattern.GetScheme() == + ContentSettingsPattern::SCHEME_CHROMEEXTENSION) { + content_settings_uma_util::RecordContentSettingsHistogram( + "Extensions.ContentSettings.SecondaryPatternChromeExtensionScheme", + type); + } + if (primary_pattern == ContentSettingsPattern::Wildcard()) { if (secondary_pattern == ContentSettingsPattern::Wildcard()) { content_settings_uma_util::RecordContentSettingsHistogram( diff --git a/extensions/browser/api/content_settings/content_settings_store_unittest.cc b/extensions/browser/api/content_settings/content_settings_store_unittest.cc index d064d6c..117be00 100644 --- a/extensions/browser/api/content_settings/content_settings_store_unittest.cc +++ b/extensions/browser/api/content_settings/content_settings_store_unittest.cc @@ -8,10 +8,12 @@ #include <memory> +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/values.h" #include "components/content_settings/core/browser/content_settings_registry.h" #include "components/content_settings/core/browser/content_settings_rule.h" +#include "components/content_settings/core/browser/content_settings_uma_util.h" #include "components/content_settings/core/browser/content_settings_utils.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_utils.h" @@ -349,6 +351,39 @@ store()->RemoveObserver(&observer); } +TEST_F(ContentSettingsStoreTest, ChromeExtensionSchemeMetrics) { + base::HistogramTester histogram_tester; + content_settings::ContentSettingsRegistry::GetInstance(); + std::string extension_id(32, 'a'); + ContentSettingsPattern chrome_extension_pattern = + ContentSettingsPattern::FromString( + "chrome-extension://peoadpeiejnhkmpaakpnompolbglelel/"); + ContentSettingsPattern https_pattern = + ContentSettingsPattern::FromString("https://example.test/"); + + RegisterExtension(extension_id); + store()->SetExtensionContentSetting( + extension_id, chrome_extension_pattern, https_pattern, + ContentSettingsType::COOKIES, CONTENT_SETTING_ALLOW, + ChromeSettingScope::kRegular); + histogram_tester.ExpectUniqueSample( + "Extensions.ContentSettings.PrimaryPatternChromeExtensionScheme", + content_settings_uma_util::ContentSettingTypeToHistogramValue( + ContentSettingsType::COOKIES), + 1); + + RegisterExtension(extension_id); + store()->SetExtensionContentSetting( + extension_id, https_pattern, chrome_extension_pattern, + ContentSettingsType::IMAGES, CONTENT_SETTING_ALLOW, + ChromeSettingScope::kRegular); + histogram_tester.ExpectUniqueSample( + "Extensions.ContentSettings.SecondaryPatternChromeExtensionScheme", + content_settings_uma_util::ContentSettingTypeToHistogramValue( + ContentSettingsType::IMAGES), + 1); +} + TEST_F(ContentSettingsStoreTest, SetExtensionContentSettingFromList) { content_settings::ContentSettingsRegistry::GetInstance(); diff --git a/extensions/test/DEPS b/extensions/test/DEPS index d70103cd..0b22280d 100644 --- a/extensions/test/DEPS +++ b/extensions/test/DEPS @@ -1,4 +1,5 @@ include_rules = [ + "+components/content_settings/core/common", "+content/public", "+ui/aura/test", "+ui/gl", diff --git a/extensions/test/extensions_unittests_main.cc b/extensions/test/extensions_unittests_main.cc index d9e86fa1..ce77637d 100644 --- a/extensions/test/extensions_unittests_main.cc +++ b/extensions/test/extensions_unittests_main.cc @@ -10,6 +10,7 @@ #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_io_thread.h" #include "build/buildflag.h" +#include "components/content_settings/core/common/content_settings_pattern.h" #include "content/public/common/content_client.h" #include "content/public/test/content_test_suite_base.h" #include "content/public/test/unittest_test_suite.h" @@ -22,6 +23,9 @@ namespace { +const char* const kNonWildcardDomainNonPortSchemes[] = { + extensions::kExtensionScheme}; + // Content client that exists only to register chrome-extension:// scheme with // the url module. // TODO(jamescook): Should this be merged with ShellContentClient? Should this @@ -69,6 +73,9 @@ { ExtensionsContentClient content_client; RegisterContentSchemes(&content_client); + ContentSettingsPattern::SetNonWildcardDomainNonPortSchemes( + kNonWildcardDomainNonPortSchemes, + std::size(kNonWildcardDomainNonPortSchemes)); } RegisterInProcessThreads(); diff --git a/tools/metrics/histograms/metadata/extensions/histograms.xml b/tools/metrics/histograms/metadata/extensions/histograms.xml index f74087d..4645bffc 100644 --- a/tools/metrics/histograms/metadata/extensions/histograms.xml +++ b/tools/metrics/histograms/metadata/extensions/histograms.xml @@ -410,8 +410,24 @@ </histogram> <histogram + name="Extensions.ContentSettings.PrimaryPatternChromeExtensionScheme" + enum="ContentType" expires_after="2025-02-28"> + <owner>[email protected]</owner> + <owner>[email protected]</owner> + <summary> + An entry is emitted each time an extension sets a content setting whose + primary pattern has a Chrome extension scheme. This will be used to + determine if the ability to set content settings for Chrome extension + origins can be deprecated. + + This happens on profile startup (for stored settings) and each time an + extension calls chrome.contentSettings[type].set(...). + </summary> +</histogram> + +<histogram name="Extensions.ContentSettings.PrimaryPatternUniqueSecondaryPatternDifferent" - enum="ContentType" expires_after="2024-12-24"> + enum="ContentType" expires_after="2025-02-28"> <owner>[email protected]</owner> <owner>[email protected]</owner> <summary> @@ -454,7 +470,7 @@ <histogram name="Extensions.ContentSettings.PrimaryPatternWildcardSecondaryPatternUnique" - enum="ContentType" expires_after="2024-12-08"> + enum="ContentType" expires_after="2025-02-28"> <owner>[email protected]</owner> <owner>[email protected]</owner> <summary> @@ -468,7 +484,7 @@ <histogram name="Extensions.ContentSettings.PrimaryPatternWildcardSecondaryPatternWildcard" - enum="ContentType" expires_after="2025-01-26"> + enum="ContentType" expires_after="2025-02-28"> <owner>[email protected]</owner> <owner>[email protected]</owner> <summary> @@ -480,6 +496,22 @@ </summary> </histogram> +<histogram + name="Extensions.ContentSettings.SecondaryPatternChromeExtensionScheme" + enum="ContentType" expires_after="2025-02-28"> + <owner>[email protected]</owner> + <owner>[email protected]</owner> + <summary> + An entry is emitted each time an extension sets a content setting whose
Regression Test / PoC
diff --git a/extensions/browser/api/content_settings/content_settings_store_unittest.cc b/extensions/browser/api/content_settings/content_settings_store_unittest.cc
index d064d6c..117be00 100644
--- a/extensions/browser/api/content_settings/content_settings_store_unittest.cc
+++ b/extensions/browser/api/content_settings/content_settings_store_unittest.cc
@@ -8,10 +8,12 @@
#include <memory>
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "components/content_settings/core/browser/content_settings_registry.h"
#include "components/content_settings/core/browser/content_settings_rule.h"
+#include "components/content_settings/core/browser/content_settings_uma_util.h"
#include "components/content_settings/core/browser/content_settings_utils.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_utils.h"
@@ -349,6 +351,39 @@
store()->RemoveObserver(&observer);
}
+TEST_F(ContentSettingsStoreTest, ChromeExtensionSchemeMetrics) {
+ base::HistogramTester histogram_tester;
+ content_settings::ContentSettingsRegistry::GetInstance();
+ std::string extension_id(32, 'a');
+ ContentSettingsPattern chrome_extension_pattern =
+ ContentSettingsPattern::FromString(
+ "chrome-extension://peoadpeiejnhkmpaakpnompolbglelel/");
+ ContentSettingsPattern https_pattern =
+ ContentSettingsPattern::FromString("https://example.test/");
+
+ RegisterExtension(extension_id);
+ store()->SetExtensionContentSetting(
+ extension_id, chrome_extension_pattern, https_pattern,
+ ContentSettingsType::COOKIES, CONTENT_SETTING_ALLOW,
+ ChromeSettingScope::kRegular);
+ histogram_tester.ExpectUniqueSample(
+ "Extensions.ContentSettings.PrimaryPatternChromeExtensionScheme",
+ content_settings_uma_util::ContentSettingTypeToHistogramValue(
+ ContentSettingsType::COOKIES),
+ 1);
+
+ RegisterExtension(extension_id);
+ store()->SetExtensionContentSetting(
+ extension_id, https_pattern, chrome_extension_pattern,
+ ContentSettingsType::IMAGES, CONTENT_SETTING_ALLOW,
+ ChromeSettingScope::kRegular);
+ histogram_tester.ExpectUniqueSample(
+ "Extensions.ContentSettings.SecondaryPatternChromeExtensionScheme",
+ content_settings_uma_util::ContentSettingTypeToHistogramValue(
+ ContentSettingsType::IMAGES),
+ 1);
+}
+
TEST_F(ContentSettingsStoreTest, SetExtensionContentSettingFromList) {
content_settings::ContentSettingsRegistry::GetInstance();
diff --git a/extensions/test/DEPS b/extensions/test/DEPS
index d70103cd..0b22280d 100644
--- a/extensions/test/DEPS
+++ b/extensions/test/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+components/content_settings/core/common",
"+content/public",
"+ui/aura/test",
"+ui/gl",
diff --git a/extensions/test/extensions_unittests_main.cc b/extensions/test/extensions_unittests_main.cc
index d9e86fa1..ce77637d 100644
--- a/extensions/test/extensions_unittests_main.cc
+++ b/extensions/test/extensions_unittests_main.cc
@@ -10,6 +10,7 @@
#include "base/test/launcher/unit_test_launcher.h"
#include "base/test/test_io_thread.h"
#include "build/buildflag.h"
+#include "components/content_settings/core/common/content_settings_pattern.h"
#include "content/public/common/content_client.h"
#include "content/public/test/content_test_suite_base.h"
#include "content/public/test/unittest_test_suite.h"
@@ -22,6 +23,9 @@
namespace {
+const char* const kNonWildcardDomainNonPortSchemes[] = {
+ extensions::kExtensionScheme};
+
// Content client that exists only to register chrome-extension:// scheme with
// the url module.
// TODO(jamescook): Should this be merged with ShellContentClient? Should this
@@ -69,6 +73,9 @@
{
ExtensionsContentClient content_client;
RegisterContentSchemes(&content_client);
+ ContentSettingsPattern::SetNonWildcardDomainNonPortSchemes(
+ kNonWildcardDomainNonPortSchemes,
+ std::size(kNonWildcardDomainNonPortSchemes));
}
RegisterInProcessThreads();
Original Bug Report
Security: Chrome extension able to grant itself content setting permissions due to faulty pattern matching
A chrome extension, with the help of permissions - contentSettings and activeTab, can grant itself access to all the features like geolocation data, microphone, camera etc. without exclusively asking it from the End User.
VULNERABILITY DETAILS
Normally (as per the codebase https://chromium.googlesource.com/chromium/chromium/+/master/chrome/common/content_settings_pattern.cc#288 ), allowed patterns are:
- [*.]domain.tld (matches domain.tld and all sub-domains)
- host (matches an exact hostname)
- a.b.c.d (matches an exact IPv4 ip)
- [a:b:c:d:e:f:g:h] (matches an exact IPv6 ip)
- file:///tmp/test.html (a complete URL without a host)
However, the pattern “*://chrome-extension-ID/*” can also be passed as primaryPattern and any contentSetting can be set to allow.
This will be enable the chrome extension calling the method:
chrome.contentSettings.microphone.set({
primaryPattern: ‘*://chrome-extension-ID/*’,
setting: ‘allow’
}, function(){});
to gain access to the microphone and act as a spyware.
VERSION
Chrome Version: Tested on v53.0.2785.116 and above [stable]
Operating System: Ubuntu 16.04 (64-bit), Windows 8, Windows 10 (will exist for Mac as well)