data: URI with bogus type is content-sniffed instead of being treated as text/plain

RESOLVED FIXED in Firefox 64

Status

()

P2
normal
RESOLVED FIXED
6 years ago
5 months ago

People

(Reporter: cyber-punk, Assigned: valentin)

Tracking

(Blocks: 1 bug)

unspecified
mozilla64
x86
macOS
Points:
---

Firefox Tracking Flags

(firefox64 fixed)

Details

(Whiteboard: [necko-backlog])

Attachments

(3 attachments)

(Reporter)

Description

6 years ago
Created attachment 794248 [details]
Video with demonstration of this bug

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36

Steps to reproduce:

We have test html page on some host with this html:

<script>document.cookie="secret_main=1"</script><h1>Main

<iframe src="data:sometext, <h1>Frame<script>alert(top.document.cookie);</script>">


Actual results:

We have access to page inside the frame, so we can execute js for stealing cookies, for example.


Expected results:

Browser should automatically download file with our incorrect MIME type.
There's really no SOP bypass because all you have to do is change that to "data:text/html," and you can legitimately access the contents.

We may be mishandling the data: protocol for unknown mime types, will have to check the spec on that. It's possible it's correct to fall-back to assuming text/html, though I would have expected text/plain.
Component: Untriaged → Networking
Product: Firefox → Core
From a quick test, if the same data: URL is used in FF's address bar, it runs there as it was text/html... we do see a JS dialog.

In Chrome, the iframe does not execute JS, and if I try the same data: URL in their address bar, the browser downloads it, as would be expected with something that had an unknown MIME type.
The "scary" and unexpected bit here is that Firefox treats data: content as coming from the same origin as that which served it. There's HTML spec support for this position, but we're the only browser that does that. It's an issue for other bugs, but that would be the "security" angle here so I'm going to unhide this bug.

This bug is about the fact that we treat data: URLs with unknown content types as text/html, whereas Chrome appears to treat them as application/octet-stream (i.e. unknown). What does the spec say? I could believe text/plain but text/html seems a dangerous default.
Group: core-security
Nothing actually defines the processing model for data: very well.  A missing content-type is specified to be text/plain, but nothing defines what happens if what you have is not even a content-type at all.

It looks like the data: protocol handler gets the string "sometext" and then tries to SetContentType with it.  SetContentType will be a no-op if the string is missing a '/', among other things, and the default type for an nsBaseChannel is UNKNOWN_CONTENT_TYPE.  That then kicks us into the content sniffer, and there we are.

I think the data channel should check for mContentType being unknown after the set, and if so replace it with application/octet-stream.

Jason, thoughts?
Flags: needinfo?(jduell.mcbugs)
Status: UNCONFIRMED → NEW
Ever confirmed: true
Whiteboard: [necko-backlog]
Anne, what does your update data: spec end up doing in this case?
Flags: needinfo?(annevk)

Comment 8

a year ago
https://github.com/whatwg/fetch/pull/579 is written in terms of "valid MIME type" and falls back to "text/plain;charset=US-ASCII" if it's not. So this would consistently render as text which is what Chrome does these days (also for top-level).

(My plan is to change "valid MIME type" to invoke a MIME type parser and only if that parser returns missing or failure to use the fallback. It would end up returning failure here due to a missing /.)
Flags: needinfo?(annevk)

Updated

a year ago
Duplicate of this bug: 1186789

Updated

a year ago
Blocks: 1392241
Summary: Bypassing SOP via incorrect MIME type in "data:" → data: URI with bogus type is content-sniffed instead of being treated as text/plain

Comment 10

a year ago
Valentin--take a look when you have time.  Sounds like plan in comment 4 ought to work.
Flags: needinfo?(jduell.mcbugs) → needinfo?(valentin.gosu)

Comment 11

a year ago
I don't think comment 4 is the way to go as it does not get us toward compatibility with Chrome. In particular, I don't think the fallback should be application/octet-stream as per comment 8.
(Assignee)

Comment 13

5 months ago
Created attachment 9006731 [details]
Bug 908413 - Make dom::MimeType a template to make it usable with nsCString r=hsivonen!
(Assignee)

Comment 14

5 months ago
Created attachment 9006732 [details]
Bug 908413 - Use dom::CMimeType::Parse to extract content type for data URIs r=hsivonen!

Depends on D5094
(Assignee)

Updated

5 months ago
Assignee: nobody → valentin.gosu
Flags: needinfo?(valentin.gosu)
Priority: P3 → P2
Comment on attachment 9006731 [details]
Bug 908413 - Make dom::MimeType a template to make it usable with nsCString r=hsivonen!

Henri Sivonen (:hsivonen) has approved the revision.
Attachment #9006731 - Flags: review+
Comment on attachment 9006732 [details]
Bug 908413 - Use dom::CMimeType::Parse to extract content type for data URIs r=hsivonen!

Henri Sivonen (:hsivonen) has approved the revision.
Attachment #9006732 - Flags: review+

Comment 18

5 months ago
Pushed by valentin.gosu@gmail.com:
https://hg.mozilla.org/integration/autoland/rev/95bd6ba098c0
Make dom::MimeType a template to make it usable with nsCString r=hsivonen

Comment 19

5 months ago
Pushed by valentin.gosu@gmail.com:
https://hg.mozilla.org/integration/autoland/rev/cbf8c92608e3
Use dom::CMimeType::Parse to extract content type for data URIs r=hsivonen

Comment 20

5 months ago
bugherder
https://hg.mozilla.org/mozilla-central/rev/95bd6ba098c0
https://hg.mozilla.org/mozilla-central/rev/cbf8c92608e3
Status: NEW → RESOLVED
Last Resolved: 5 months ago
status-firefox64: --- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla64
You need to log in before you can comment on or make changes to this bug.