Closed Bug 1657916 (CVE-2020-35111) Opened 8 months ago Closed 6 months ago

proxy.onRequest does not catch "view-source" URIs when used with the <all_urls> filter

Categories

(WebExtensions :: Request Handling, defect, P2)

79 Branch
x86_64
Linux
defect

Tracking

(firefox-esr7884+ verified, firefox79 wontfix, firefox80 wontfix, firefox81 wontfix, firefox82 wontfix, firefox83 wontfix, firefox84+ verified)

VERIFIED FIXED
84 Branch
Tracking Status
firefox-esr78 84+ verified
firefox79 --- wontfix
firefox80 --- wontfix
firefox81 --- wontfix
firefox82 --- wontfix
firefox83 --- wontfix
firefox84 + verified

People

(Reporter: y.tioual, Assigned: mixedpuppy)

References

Details

(Keywords: csectype-disclosure, sec-low, Whiteboard: [adv-main84+][adv-esr78.6+])

Attachments

(2 files)

User Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36

Steps to reproduce:

When using FoxyProxy or Proxy SwitchyOmega (the two most downloaded proxy switcher extensions), I noticed that requests do not get proxied when using the "view-source" scheme.

Steps to reproduce:

  1. Setup FoxyProxy or Proxy SwitchyOmega to proxy traffic to an external proxy (different public IP address)
  2. Go to https://ipinfo.io/ip . You'll see the proxy's IP address.
  3. Now go to view-source:https://ipinfo.io/ip?x=x . You'll see your network's IP address (?x=x is mainly used as a cachebuster to prevent showing the same IP address that was cached after the first request)

This was tested on FoxyProxy 7.5.1 and Proxy SwitchyOmega 2.5.20

Actual results:

This behavior discloses a user's real IP address.

This scenario can happen really often amongst web developpers and security researchers, when the source code is inspected using Ctrl+U and then later on, HTTP parameters are modified (and thus a new request using "view-source" is made) to see the effect they have on the webpage.

When inspecting FoxyProxy, I noticed that they use proxy.onRequest API (which is the recommended way since Firefox 68) to proxy requests:

(background.js lines 185 & 194)
browser.proxy.onRequest.addListener(proxyRequest, {urls: ["<all_urls>"]});

By setting a break point on the "proxyRequest" function, I noticed that this function is never called when using the "view-source" scheme. The documentation shows that <all_urls> filter does not support this scheme:

https://developer.mozilla.org/fr/docs/Mozilla/Add-ons/WebExtensions/Match_patterns

Exploitation of this behavior is pretty much unlikely, as redirecting a user to a URI with a "view-source" scheme will get blocked by the SOP. However, users can inadvertedly leak their IP address.

Expected results:

Even if (to my understanding) FoxyProxy does not support the "view-source" scheme (I plan on opening a bug request once this is resolved), the <all_urls> filter should be able to include URIs that have "view-source" as a scheme.

OS: Unspecified → Linux
Hardware: Unspecified → x86_64

Bugbug thinks this bug should belong to this component, but please revert this change in case of error.

Component: Untriaged → Networking
Product: Firefox → Core

I've looked this a bit.
It seems that ChannelWrapper::Matches returns false at here because the url is not matched. The final url here is view-source:https://ipinfo.io/ip?x=x. I guess the extension code or something else doesn't expect to process the url with view-source scheme.

Component: Networking → Request Handling
Product: Core → WebExtensions

Hello,

I’ve managed to reproduce the issue on the latest Nightly (81.0a1/20200811091731), Beta (80.0b6/20200807195315) and Release (79.0/20200720193547) under Windows 10 Pro 64-bit and Ubuntu 16.04 LTS.

I’ve configured both proxy add-ons mentioned in the report with this server address 110.164.253.85 on port 8080. When I’ve accessed https://ipinfo.io/ip, the correct proxy address was displayed. Accessing view-source:https://ipinfo.io/ip?x=x afterwards, however, displayed the real IP address of my machine (sometimes a refresh was required for the real IP to be displayed), thus confirming the issue.

Status: UNCONFIRMED → NEW
Has STR: --- → yes
Ever confirmed: true

The severity field is not set for this bug.
:mixedpuppy, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(mixedpuppy)
Severity: -- → S2
Flags: needinfo?(mixedpuppy)
Priority: -- → P2
Assignee: nobody → mixedpuppy
Flags: sec-bounty?

AFAIU, this is in WebRequest code, so the leak doesn't occur with typical proxy settings. The issue is solely in the APIs we provide for writing proxy-like extensions, correct? I.e., there is no leak when using "typical" proxy settings, correct?
I wonder why folks would use WebRequest when we do have a proxy API

I would call it sec-low, unless there is a way to trigger a view-source load from content. If we (or the reporter) finds a way to leak this from an evil website, I'd rate it sec-moderate.

Group: core-security-release

You are correct, the typical proxy settings are not affected by this leak.
When I inspected both extensions, they do indeed use the Proxy API and not WebRequest, so I guess this is an issue in the Proxy API.

I am still investigating how one could trigger a view-source from a controlled page. The only way I found so far is by setting the "security.view-source.reachable-from-inner-protocol" to "true" and setting an attacker-controlled URL as the src of an img tag in the page, but it requires user interaction so I don't consider this a valid case.

I'll keep you updated if I find a bypass to this.

(In reply to Yassine Tioual from comment #6)

"security.view-source.reachable-from-inner-protocol" to "true"

Bah, that pref still exists? Ugh. Thanks for reminding me. I filed bug 1661672 to get rid of it.

The webrequest side of this is bug 1439163, I think?

Seems like there is confusion here about proxy and webrequest. In terms of a privacy leak, this is a proxy api issue.

In terms of the actual problem, ChannelWrapper is the underlying issue that affects both of them.

View source prefixes urls with a view-source scheme. Somewhere along
the way a request is made for the un-prefixed url but we do not intercept. This
removes the prefix for webrequest and proxy APIs prior to checking access rules
and filters, allowing the APIs to intercept those requests that the otherwise
could.

Hrm, I just realized this is marked as a security issue. It really isn't anything that I think needs to be non-public.

We generally consider proxy bypasses that are triggered from web content in a non-webextension settings as sec-high, so I wanted to err on the side of caution.

This was under the assumption that the reporter may find a method to bypass a proxy that can be triggered from web content (in comment 5). I'd rather have this bug private and turn out less bad as we thought than public and then become worse. As per comment 6, this seems not to be the case? As a sec-low bug, you can just land the patch without any extra approval and we can make the bug public thereafter.

Duplicate of this bug: 1666457
Flags: sec-bounty? → sec-bounty-
Status: NEW → RESOLVED
Closed: 6 months ago
Resolution: --- → FIXED
Target Milestone: --- → 83 Branch

Is this something we need to consider uplifting?

Flags: needinfo?(mixedpuppy)
Flags: in-testsuite+
Target Milestone: 83 Branch → 84 Branch
Flags: qe-verify+
Whiteboard: [post-critsmash-triage]

Hello,

Verified the fix using the latest Nightly (84.0a1/20201028092421) under Windows 10 Pro 64-bit and Ubuntu 16.04 LTS.

Similar to Comment 3, I’ve configured both add-ons with this server address 103.206.105.193 on port 3629 and accessed https://ipinfo.io/ip. The correct proxy address was displayed. Accessing view-source:https://ipinfo.io/ip?x=x afterwards, also displayed the proxied address, thus confirming the fix.

Status: RESOLVED → VERIFIED
Flags: qe-verify+
Whiteboard: [post-critsmash-triage]

Per Slack discussion, it sounds like we want to let this ride the next cycle rather than uplifting.

Comment on attachment 9173508 [details]
Bug 1657916 allow extensions to see view-source requests

ESR Uplift Approval Request

  • If this is not a sec:{high,crit} bug, please state case for ESR consideration: view-source requests are not caught by proxies in extensions, so this is a touch of a leak. We've lived with it for a long time, but since esr is long lived, it would be good to uplift it. We otherwise intend this to just ride the train on normal releases.
  • User impact if declined: view-source requests may not be proxied
  • Fix Landed on Version: 84
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): It's a small change with a good set of tests on it.
  • String or UUID changes made by this patch:
Flags: needinfo?(mixedpuppy)
Attachment #9173508 - Flags: approval-mozilla-esr78?

Comment on attachment 9173508 [details]
Bug 1657916 allow extensions to see view-source requests

Approved for 78.6esr.

Attachment #9173508 - Flags: approval-mozilla-esr78? → approval-mozilla-esr78+
Duplicate of this bug: 1680213
Flags: qe-verify+
Duplicate of this bug: 1439163
QA Whiteboard: [qa-triaged]

Hello,

Verified the fix using the latest ESR (78.6.0esr/20201207224150) under Windows 10 Pro 64-bit and Ubuntu 16.04 LTS.

I’ve configured both add-ons with this server address 82.200.233.4 on port 3128 and accessed https://ipinfo.io/ip. The correct proxy address was displayed. Accessing view-source:https://ipinfo.io/ip?x=x afterwards, also displayed the proxied address, thus confirming the fix.

Flags: qe-verify+
Whiteboard: [adv-main84+] → [adv-main84+][adv-esr78.6+]
Regressions: 1678734
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.