Closed Bug 1564588 (CVE-2019-11748) Opened 5 years ago Closed 5 years ago

Deep-linking to attacker-created rooms on already-trusted WebRTC sites may give unprompted camera/mic access

Categories

(Core :: WebRTC: Audio/Video, defect, P2)

defect

Tracking

()

VERIFIED FIXED
Tracking Status
firefox-esr60 --- wontfix
firefox-esr68 69+ verified
firefox68 - wontfix
firefox69 + verified
firefox70 + verified

People

(Reporter: jib, Assigned: jib)

Details

(Keywords: privacy, sec-moderate, Whiteboard: [adv-main69+][adv-esr68.1+])

Attachments

(3 files)

This is to record reasons to accelerate landing of feature policy, and to consider putting getUserMedia behind a user gesture, at least in deep link navigation cases where permission has been persisted.

In light of the recent Zoom exploit, it's prudent to review our camera & microphone permission handling. The zoom exploit allowed any web site—even third-party banner ads—to launch a user's installed zoom client into an attacker-created room with the user's camera and microphone turned on. It could do this from a background tab, at any time of the attacker’s choosing. The attacker could then record the user (or their environment if the user isn't present atm).

Firefox fares better than Zoom, not allowing this by default, but is not 100% free of similar issues.

A web-equivalent exploit would be a site or iframe (banner ad) navigating to an attacker-created room on a well-known already-trusted WebRTC site, using a deep link. In Firefox, "already-trusted" means the user has previously checked ☑ Remember this decision in the gUM prompt at the well-known WebRTC site. It's worth looking at the third party (banner ad) and first-party cases separately:

In the first-party case, the exploit merely requires the trusted WebRTC site to start the call immediately and without interaction, which many do (but again, relies on you having used the well-known site before and having granted it persistent permission in the past).

In the third-party case, the exploit additionally requires a user-trusted WebRTC service shady enough to allow itself to be iframed (not using CSP to prevent this).

The good news is Firefox:

  • does not persist camera & microphone permissions by default (opt in)
  • does not grant gUM access to background tabs (waits for focus)
  • Once feature policy lands (soon) iframes (banner ads) will be blocked from gUM access by default.

The bad news is Firefox:

  • allows gUM access on pageload—doesn't gate getUserMedia behind a user gesture.
  • feature policy hasn't landed yet.

This means that if a Firefox user has selected ☑ Remember this decision in the gUM prompt for a well-known WebRTC site, then they are vulnerable from this exploit. Once feature policy lands, it takes care of the third-party case, leaving the first-party case.

Complications: A problem with always requiring a user gesture would be that in the Firefox permission model, it leaves Firefox users with two clicks instead of one to enter a room, compared with Chrome. For example: Today, you click on a link a friend sent you over DM, you see a Firefox permission prompt asking for camera & mic permission for the well-known WebRTC site, you click "Allow", and you're in. Requiring a user gesture would mean a second (in-content) click to enter. Maybe we only require it if permission is persisted?

Group: core-security

To clarify the need for feature policy, I think we consider third party sites being able to do this as more indefensible than first-party sites doing it.

There are some legitimate use-cases for first-party sites being allowed to do this (jump into room links), but none for third party sites.

Personally I would be hesitant to introduce a user gesture for this permission. It already has excellent response metrics and we would probably break a lot of sites.

In bug 1565574 we landed on "remember this decision should be double keyed by origin + app", which is the equivalent of what we have for WebRTC already (it's already keyed by origin, but we don't need an app).

At some point we just have to offload the security aspect of this to websites, and I think we're in a reasonable state for WebRTC.

An example of the CSP mitigation for sites mentioned above would be:

Content-Security-Policy: frame-ancestors 'none';

A demo iframing Jitsi. Putting it here to refer to and test with.

Chrome considers this a request from the top-level origin (bugzilla.mozilla.org) for persistent permission and name in prompt, whereas
Firefox considers this a request from the iframe origin (meet.jit.si) with regard to persistent permission and name in prompt.

Problems:

  1. A Firefox user who's used jitsi in the past with persisted permission would be vulnerable to a malicious site getting the camera and microphone this way, if not for the fact that jitsi appears to disable the camera and microphone by default in this case, a mitigation on their part.
  2. (To the extent people read text in prompts) Firefox's permission prompt is confusing.

Importantly, this is a problem even with feature policy enabled, since the top-level domain is the attacker and can add the allow="camera;microphone" to a hidden iframe. We should open a bug if we don't have one to fix our permissions like I explain in w3c/permissions#185 which appears to be how Chrome works now.

I've tested several common WebRTC sites, and most of them have a “Ready to join?” button, even with deep links. The exceptions so far are appear.in (which prevents iframing 👍) and jitsi (which does not, but appears to turn off cam/mic by default in this case 👍).

Still looking for a bad apple to test with, since one is all it takes, though it helps that it can't be too obscure in order to be an effective hack.

I think a short-term upliftable minimal fix would be to ignore persisted permissions when invoked from iframes.

(In reply to Jan-Ivar Bruaroey [:jib] (needinfo? me) from comment #4)

I think a short-term upliftable minimal fix would be to ignore persisted permissions when invoked from iframes.

Johann, would you be able to write a patch for this or point me in the right direction? Looks like this would need to be done in WebrtcUI.jsm (desktop)?

Flags: needinfo?(jhofmann)

Changing this to a review request.

Assignee: nobody → jib

Thanks for doing a patch!

Importantly, this is a problem even with feature policy enabled, since the top-level domain is the attacker and can add the allow="camera;microphone" to a hidden iframe. We should open a bug if we don't have one to fix our permissions like I explain in w3c/permissions#185 which appears to be how Chrome works now.

That GitHub thread seems to conflict with how we want to build our permission model alongside feature policy. With our update, no third party origin will request permission anymore, any permission request will always come from the first party, which then may decide to choose how to distribute the permission. Thus, there will not be two doorhangers or anything, if the first party has access any embeddee may have access if the first party deems it acceptable. Otherwise their permission requests will be blocked outright.

With feature policy, what you describe in comment 4 isn't our problem anymore. If the user decides to give trust to the first party then there's hardly anything we can do to prevent said part to share the user's camera data with third parties anyway. The site could just stream the keyframes via postMessage or simply send the data directly to the server of the third party.

Feature policy is explicitly an opt-in feature for websites to add security by restricting their embedded third parties, and only passively helps users by simplifying our permission model.

Flags: needinfo?(jhofmann)

(In reply to Johann Hofmann [:johannh] from comment #8)

We should open a bug if we don't have one to fix our permissions like I explain in w3c/permissions#185 which appears to be how Chrome works now.

That GitHub thread seems to conflict with how we want to build our permission model alongside feature policy. With our update, no third party origin will request permission anymore, any permission request will always come from the first party, which then may decide to choose how to distribute the permission.

How? What "update" are you referring to? On nightly, where I believe feature policy is already enabled, I still see "Will you share cam & mic with meet.jit.si" in comment 4.

I believe the github thread is describing the same goal you describe: that end-users see all requests as coming from the top-level site only. If that's what you mean by "no third party origin will request permission anymore", then I agree. But as an implementation comment, I'm not following who's code will need to deal with comment 4. There's no MediaManager patch coming to have a top-level document ask for gum permissions on behalf of an iframe.

Clearly third parties will still request camera and microphone through getUserMedia. In the specs—which is what the github thread concerns—getUserMedia calls request permission to use in step 6.3.5. This means that the latter algorithm's "realm and other realms with the same origin." is referring to the document, realm and origin of the iframe, not the top-level document. That's where it finds the policy controlled feature in permission state. I would similarly expect our permission code to handle this. That's why I reopened the github issue to allow persisting to the granting origin.

Thus, there will not be two doorhangers or anything, if the first party has access any embeddee may have access if the first party deems it acceptable. Otherwise their permission requests will be blocked outright.

Agreed.

With feature policy, what you describe in comment 4 isn't our problem anymore. If the user decides to give trust to the first party then there's hardly anything we can do to prevent said part to share the user's camera data with third parties anyway. The site could just stream the keyframes via postMessage or simply send the data directly to the server of the third party.

Agreed once we fix our permission prompt to name the top-level domain, and persist permission to the top-level domain instead of the iframe's.

Please let me know if this matches your understanding, or if I'm off track.

Flags: needinfo?(jhofmann)
Flags: needinfo?(jhofmann)

How? What "update" are you referring to? On nightly, where I believe feature policy is already enabled, I still see "Will you share cam & mic with meet.jit.si" in comment 4.

The new permission model ("updating" our handling of permission requests for iframes) is not a part of feature policy, it just requires feature policy to work properly. So FP is implemented but the permission changes are still pending (lack of resources).

I admit that in terms of code there will still be a time when a third-party principal initiates a permission request. My main point is that for persistent permissions, with feature policy we will never check those for the third party origin and always for the first party. The attack you describe here is based on persistent permissions and thus feature policy will, completely, prevent it.

Agreed once we fix our permission prompt to name the top-level domain, and persist permission to the top-level domain instead of the iframe's.

Yup, that's the plan :)

(In reply to Johann Hofmann [:johannh] from comment #11)

... the permission changes are still pending (lack of resources).

Looking forward to those. Do you have a bug #?

Note sites like https://jitsi.org/ appear to have legitimate partners iframing them. Once this patch here lands, end-users of their services will be stuck with no way to persist camera and microphone permission on desktop until those permission changes are made.

[Tracking Requested - why for this release]: Potential exploitable weakness. Known outside of Mozilla by person waiting on us to fix it before blogging about it.

Comment on attachment 9083497 [details]
Bug 1564588 - No longer persist third-party permission.

Beta/Release Uplift Approval Request

  • User impact if declined: If there's just one vulnerable semi-popular room-based WebRTC site out there that allows itself to be iframed AND throws its users into meetings using deep-links with persisted camera/mic on, without gating them on some "Join meeting" button, THEN the following exploit seems doable (so far the only vulnerable site we've identified, Jitsi, has added mitigations by joining users without camera/mic on in this case, but we haven't done an extensive search. Many other sites like appear.in typically use CSP to prevent iframing, and are not affected. But there may be product reasons why a site allows iframing. See comment 4).

The exploit is that any web site—even an iframed third-party banner ad, could embed the vulnerable site in a hidden iframe away from view, and specify an attacker's room in the URL. This could connect a victim's system to an attacker's room without their knowledge, potentially enabling the attacker to spy on the victim using camera or microphone or both. There might not be any hardware light indication if only microphone is used.

Victims vulnerable to this unprompted snooping are limited to users who have previously checked ☑ Remember this decision in the permission prompt in a previous visit to the vulnerable site.

There's a potentially larger pool of vulnerable users who've never visited the vulnerable site, who may get a prompted, but be confused since the wrong domain is listed in the permission prompt, and accept it for that reason, but in my view that risk is less severe, since such an exploit would probably be spotted pretty quickly.

  • Is this code covered by automated tests?: Yes
  • Has the fix been verified in Nightly?: Yes
  • Needs manual test from QE?: No
  • If yes, steps to reproduce:
  • List of other uplifts needed: None
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): The risk is low because the patch is simple. It simply disables persistent permissions in cross-origin (third-party) iframes.

There's some backlash risk in the sense that legitimate end-users of WebRTC services embedded in iframes (e.g. Jitsi partners—not Jitsi itself) will now be prompted by Firefox for camera and microphone every time on desktop, and no longer be able to persist their camera and mic permissions in Firefox for that site (this matches Firefox for Android today where we never persist camera and microphone). Fixing this requires more work in the future (see comment 11).

  • String changes made/needed: None

ESR Uplift Approval Request

  • If this is not a sec:{high,crit} bug, please state case for ESR consideration: See above.
  • User impact if declined: See above.
  • Fix Landed on Version:
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): See above.
  • String or UUID changes made by this patch: None
Attachment #9083497 - Flags: approval-mozilla-release?
Attachment #9083497 - Flags: approval-mozilla-esr68?
Attachment #9083497 - Flags: approval-mozilla-beta?
Attachment #9084405 - Flags: approval-mozilla-release? approval-mozilla-esr68?
Attachment #9084405 - Flags: approval-mozilla-release?
Attachment #9084405 - Flags: approval-mozilla-beta?

Why is this leave-open? Is it actually fixed in nightly or not?

Comment on attachment 9083497 [details]
Bug 1564588 - No longer persist third-party permission.

This doesn't seem to warrant a dot release AFAICT?

Attachment #9083497 - Flags: approval-mozilla-release? → approval-mozilla-release-

I only marked it "leave open" since comment 0 mentions two ways to deeplink into attacker rooms, 1) from top-level domain solely through navigating to a vulnerable WebRTC site with attacker-room in URL without the user's intent, and 2) from embedded iframe that does so on the sly, maybe even visually hiding that this is taking place.

Since I gather the risk profiles are quite different, I'm happy to open a new issue on the former, so we can close this out.

This doesn't seem to warrant a dot release AFAICT?

Since jitsi has added a mitigation on their servers, I don't know of another WebRTC site at the moment that is vulnerable. But I didn't do an extensive search, so that doesn't mean there isn't one (or that someone couldn't build one). I tested hangouts, Google meet, talky.io, appear.in, and jitsi. I did NOT test Facebook or webex for instance (I'm on PTO now, if someone wants to do that).

If we don't do a dot release I think we need to ask the person outside of Mozilla to hold off blogging about it until 69 becomes release.

Even without an identified exploit, I'd predict the potential press around this might be negative, given how last month's non-technical press (e.g. Fortune) seemed more upset about the privacy implications than over zoom's RCE (!)

Keywords: leave-open
Group: media-core-security → core-security-release
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → FIXED

Comment on attachment 9083497 [details]
Bug 1564588 - No longer persist third-party permission.

Fixes a WebRTC sec issue. Approved for 69.0b13 and 68.1esr.

Attachment #9083497 - Flags: approval-mozilla-esr68?
Attachment #9083497 - Flags: approval-mozilla-esr68+
Attachment #9083497 - Flags: approval-mozilla-beta?
Attachment #9083497 - Flags: approval-mozilla-beta+
Attachment #9084405 - Flags: approval-mozilla-esr68?
Attachment #9084405 - Flags: approval-mozilla-esr68+
Attachment #9084405 - Flags: approval-mozilla-beta+
Flags: qe-verify+
QA Whiteboard: [qa-triaged]

Considering the "qe-verify+" tag, I would like to verify the fix of this bug. Please offer some steps to reproduce or some explanations on whats the best way to verify it. Thanks!

Flags: needinfo?(jib)

Can any of you guys help with some steps to reproduce?

Flags: needinfo?(jhofmann)
Flags: needinfo?(bogdan.maris)

Here's an STR:

  1. Open https://meet.jit.si/test123456 in a new tab
  2. When prompted for camera and microphone, check "Remember this decision" and approve (you can leave this tab open for full effect)
  3. Open attachment 9083434 [details] in a new tab (jib's manual test page attached to this bug)
  4. Enable camera through jitsi's UI in the attachment's iframe

Expected pre-patch:
Camera turns on and transmits your face to the other tab you have open D:

Expected post-patch:
A permission prompt with no "Remember this decision" checkbox available

Flags: needinfo?(jib)
Flags: needinfo?(jhofmann)
Flags: needinfo?(bogdan.maris)

I have reproduced the issue in Nightly v70.0a1 from 2019-08-08 and verified it in Nightly v70.0a1 from 2019-08-10 and Nightly v70.0a1 from 2019-08-18 and Beta v69.0b14 and Firefox ESR v68.1.0esr build ID: 20190816215911 on Windows 10 and Ubuntu 18.04.
The permission prompt with no "Remember this decision" checkbox is displayed after opening the video on the second "in frame" jitsi test page.

Status: RESOLVED → VERIFIED
Flags: qe-verify+
Alias: CVE-2019-11748
Whiteboard: [adv-main69+][adv-esr68.1+]
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: