Closed Bug 1578317 Opened 5 years ago Closed 4 years ago

Leaking status code of a cross-origin resource by using an audio/video tag and MediaError's messages

Categories

(Core :: Audio/Video, defect, P3)

defect

Tracking

()

RESOLVED DUPLICATE of bug 1450853
Tracking Status
firefox-esr68 --- wontfix
firefox69 --- wontfix
firefox70 --- wontfix
firefox71 --- wontfix
firefox73 --- wontfix

People

(Reporter: luan.herrera, Assigned: padenot)

References

()

Details

(Keywords: csectype-sop, sec-low, Whiteboard: [reporter-external] [client-bounty-form] [verif?])

Attachments

(1 file)

Description

By inserting a cross-origin resource into an audio/video tag it is possible to leak its status code by getting the MediaError's message.

This vulnerability is particularly useful for XS-Search attacks, whereby knowing the status code of a cross-origin resource an attacker can infer the state of certain endpoints and then leak information (more on https://github.com/xsleaks/xsleaks/wiki/Real-World-Examples).

Reproduced on Windows 10 using version 68.0.2 (64-bit).

Steps to reproduce

  1. Access https://lbherrera.github.io/lab/firefox-7a135d30/index.html
  2. Open the DevTools and check the MediaError messages on the console.

Actual results

The real status code of the cross-origin resources was leaked.

Expected results

The real status code of the cross-origin resources shouldn't have been leaked.

Flags: sec-bounty?
Group: firefox-core-security → media-core-security
Component: Security → Audio/Video
Product: Firefox → Core

I see a bunch of warnings of the form

Error: This error message will be blank when privacy.resistFingerprinting = true. If it is really necessary, please add it to the whitelist in MediaError::GetMessage:

that seems to indicate we know about this issue, and are preventing it in at least one sensitive case. That means there were probably reasons not to block this generally (required by spec, perhaps?). Tom: do you know what the story is here?

Flags: needinfo?(tom)

(In reply to Daniel Veditz [:dveditz] from comment #1)

I see a bunch of warnings of the form

Error: This error message will be blank when privacy.resistFingerprinting = true. If it is really necessary, please add it to the whitelist in MediaError::GetMessage:

that seems to indicate we know about this issue, and are preventing it in at least one sensitive case. That means there were probably reasons not to block this generally (required by spec, perhaps?). Tom: do you know what the story is here?

Yes and no. We considered that MediaErrors might return fingerprintable information, so we neutered it for the RFP case. The fact that you're seeing the message means you have Resist Fingerprinting turned on, and you're triggering a firefox-developer-intended message. =)

The issue is - almost certainly - about the situation when RFP is off.

Flags: needinfo?(tom)

I did some digging and found https://bugzilla.mozilla.org/show_bug.cgi?id=1354633#c6 which explains why MediaError's message returns empty when you have Resist Fingerprinting turned on :)

As a side note, Chrome returns an empty message for cross-origin resources and returns a message when it is a same-origin resource.

I do not have resistfingerprinting turned on. I got the warning that the message would be blank if it's turned on, and then also got the message (reproducing the bug).

Status: UNCONFIRMED → NEW
Type: task → defect
Ever confirmed: true

Sounds to me like the Chrome behavior is what we want here to be on the safe side.
Jean-Yves, Paul do you guys have any thoughts on this?

Flags: needinfo?(padenot)
Flags: needinfo?(jyavenard)

I don't believe there's anything of value in what we are leaking here. It's a conscious choice; at the time we exposed MediaResult we did a security review on the matter. At worse we get link to the source code path as compiled by the builder machine; it's not unique to the user.

We exposed on why a video didn't play or errored, because the video itself contained error, which here would be the cross-origin video. There's no sensitive information being exposed then that can't be accessed outside this method.

Flags: needinfo?(jyavenard)

(In reply to Jean-Yves Avenard [:jya] from comment #6)

There's no sensitive information being exposed then that can't be accessed outside this method.

I do not believe this is correct. When trying to load a non-video in an audio/video context we disclose the exact status code (200, 302, 404, 500, 412, 403, etc.) via the MediaError Message Outside of this context, the smallest granularity we expose (that I'm aware of) is onsuccess or onerror callbacks for resource loading.

(In reply to Tom Ritter [:tjr] from comment #7)

I do not believe this is correct. When trying to load a non-video in an audio/video context we disclose the exact status code (200, 302, 404, 500, 412, 403, etc.) via the MediaError Message Outside of this context, the smallest granularity we expose (that I'm aware of) is onsuccess or onerror callbacks for resource loading.

To clarify: does this mean that cross origin audio/video tags could be used to gain knowledge about LAN internal pages?

Flags: needinfo?(tom)

I think that's correct, this allows scanning a local network more precisely and therefore allowing easier identification. Can we just align with Chrome here, it does seem like the right thing to do? Here is a simple patch for this.

Flags: needinfo?(padenot)
Assignee: nobody → padenot
Status: NEW → ASSIGNED

This is missing tests of course. We can write them if we decide to do this.

Matching Chrome's behavior seems reasonable to me, but I don't think I'm the best person to review this.... I accepted because the code looked good to me but I think you should run this conceptually by someone else...

Flags: needinfo?(tom)

[csectype-sop because it's cross-origin information being leaked. "disclosure" is usually about leaking user/local information]

Anne, jya, I think this makes sense for the reasons mentioned earlier, would you mind double checking?

Flags: needinfo?(jyavenard)
Flags: needinfo?(annevk)

Yeah this looks good. As a reminder, for opaque responses (cross-origin without CORS) we don't want to leak data beyond width/height for image/video resources and probably duration for audio/video resources.

(And we also need to start locking down what we'll consider to be audio/image/video resources in that context as per bug 1532642.)

Flags: needinfo?(annevk)
Priority: -- → P3

As I wrote in the phabricator comment:
may as well turn off completely the message attribute then, because the main users of this attribute would be using CDN to distribute their videos and as such use cross-origin ones.

what about only clearing it outside chrome process?
at least we keep some usability with the media devtools extension.

So it can't be exploited by scripts at least.

Flags: needinfo?(jyavenard)

Most CDNs support CORS these days and per the patch it seems that if CORS is used nothing is muted here. But yeah, exposing it to devtools seems very reasonable.

(In reply to Jean-Yves Avenard [:jya] from comment #16)

As I wrote in the phabricator comment:
may as well turn off completely the message attribute then, because the main users of this attribute would be using CDN to distribute their videos and as such use cross-origin ones.

what about only clearing it outside chrome process?
at least we keep some usability with the media devtools extension.

So it can't be exploited by scripts at least.

If we do that I would suggest adding an informational message that appears in devtools afterwards indicating this message is not accessible to web scripts and only appears as a debugging aid in devtools. Otherwise people are going to be REALLY confused.

When adding tests for this, I'm facing the issue that HTMLMediaElement are not considered same-origin unless there is a decoder, so if there is an error on load, we can't do this properly.

The idea seem to be that the decoder owns the channel, that knows if the resource is same-origin or cross-origin.

I found https://bugs.chromium.org/p/chromium/issues/detail?id=828265 which is Chrome's bug.

I also found https://bugs.chromium.org/p/chromium/issues/detail?id=826187 which is a related cross-origin leak (not as direct) which seems related...

Flags: sec-bounty? → sec-bounty+

FYI: it seems there's also bug 1450853 (public) with a patch now. Not sure what the best course of action is, so I'll needinfo the people involved here.

Flags: needinfo?(sstreich)
Flags: needinfo?(padenot)
Flags: needinfo?(jyavenard)
Flags: needinfo?(ckerschb)

(In reply to Anne (:annevk) from comment #21)

FYI: it seems there's also bug 1450853 (public) with a patch now. Not sure what the best course of action is, so I'll needinfo the people involved here.

I already chatted with Tom about that. Ni? him for visibility. Not sure what the best action is. Tom?

Flags: needinfo?(ckerschb) → needinfo?(tom)

I'll need to confer with Dan and I think he's OOTO this week. Leaving ni.

posted in the review; there's been no update to this patch since I reviewed it and ask for changes.

Flags: needinfo?(jyavenard)

The duplicate bounty situation is resolved.

Flags: needinfo?(tom)
Status: ASSIGNED → RESOLVED
Closed: 4 years ago
Resolution: --- → DUPLICATE
Flags: needinfo?(sstreich)
Flags: needinfo?(padenot)
Group: media-core-security
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: