Closed Bug 1726997 Opened 3 years ago Closed 2 years ago

file URLs should not be able to load other files as script unless they have an allowed extension (which should be user-configurable)

Categories

(Core :: DOM: Core & HTML, enhancement)

enhancement

Tracking

()

RESOLVED FIXED
102 Branch
Tracking Status
firefox-esr91 --- wontfix
firefox100 --- wontfix
firefox101 --- wontfix
firefox102 + fixed

People

(Reporter: omespino, Assigned: tschuster)

Details

(Keywords: sec-low, Whiteboard: [domsecurity-backlog2][reporter-external] [client-bounty-form] [verif?][adv-main102-])

Attachments

(1 file)

Attached file etc_environment.html

VERSION
Firefox latest stable version 91.0.1 (64-bit)
Operating System: Ubuntu 20.04 LST 64 bits

REPRODUCTION CASE

  1. Download and install the latest Firefox latest stable version 91.0.1 (64-bit) for ubuntu

  2. Put your attacker server to listen in any port with netcat, in my case port 80:

"sudo nc -l -p 80"

3.Open the file attached etc_enviroment.html and modify the part where IMG tag is and put your attacker server IP and save it.

4.- Just open the etc_enviroment.html on Firefox, it would contain variables from /etc/environment system file and send those to the attacker server

Explanation:

Since we can inject random HTML/js code, we can "import" files with the script tag, per example:

"<script src=file:///../../../../etc/enviroment></script>"

So if the file has the right js format the browser would load any content, since the common format of /etc/environment is like:

PATH="/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
JAVA_HOME="/opt/jre/bin"

This would actually load because those variables have the same format that javascript variables, plus since any Linux environment variables are so quite predictable we can brute force the most common variables names or iterate those variables with Object.keys(window) and send them to the attacker server

Attack scenario
An attacker can read arbitrary variables from /etc/environment on Linux through Firefox via this HTML crafted file

Flags: sec-bounty?

I looked at this a bit. I haven't confirmed precisely the STR, as I'm not on Linux, but I can indeed run a script from a file URL, at least when I loaded my test case via a different file URL. Maybe we need some kind of Cross-Origin-Resource-Policy policy that blocks cross origin access for file URIs?

Status: UNCONFIRMED → NEW
Ever confirmed: true
Summary: /etc/enviroment local variables disclosed on linux via Firefox latest stable version 91.0.1 (64-bit) → /etc/environment local variables disclosed via script element

I could not reproduce this using a data URL.
E.g., data:text/html,<script src=file:///../../../../../etc/environment></script> or just data:text/html,<script src="file:///etc/environment"></script>.

I could confirm that those file-URLs load the environment file, but I always get the following error:
<script> source URI is not allowed in this document: “file:///etc/environment”.

Fwiw, the same is true when including a <script> element on a web page.

@omespino: Did you maybe run this HTML page from a file:// URL instead of http://something?

Flags: needinfo?(omespino)

Hello Frederik,
Yes I did run this HTML from a file:// schema

Flags: needinfo?(omespino)

Thank you for clarifying. This makes it a bit less bad.
On the one hand, file's are considered cross-origin from another but generally, a file URL can load another file URL as script, because scripts are not required to be same-origin.

We ought to change that. I'm modifying the bug title to reflect that with more clarity.

I'm going to call this sec-low, because it requires a malicious file on disk that you can't easily load from the web.
One might also consider this a "low sec-moderate". This classification is not final.

Group: firefox-core-security → core-security
Type: task → defect
Component: Security → DOM: Security
Keywords: sec-low
Product: Firefox → Core
Summary: /etc/environment local variables disclosed via script element → file URLs should not be able to load other files as script

Fwiw, this change might break typical HTML documentation use cases, so it's not clear whether we will be able to make it. This bug might end up as wontfix.

(For reference, bug 1558299 is the bug report that finally got us to start treating file URLs as unique origins.)

Files URLs are unique origins, but some historical pre-CORS web features are allowed to load cross-origin resources. That includes <script> and <img> among others.

On the web we've tried to limit the damage by imposing a Content-Type requirement, although for historical webcompat reasons we still allowed text/plain for scripts which lets in a lot more than we'd like (see Should response be blocked due to MIME type?). We don't have Content-Type: on disk so that gets trickier, and developers are always inventing new extensions for types of JavaScript files so it would hurt to be too exclusive.

Could we get away with blocking the loading of files with no extension at all? Would that be enough?

Limit the loading of file:/// subresources to the user's home directory and below?

Group: core-security → dom-core-security

I think breaking the case where HTML documentation are split out into separate folders but some common scripts and styles being loaded as from a parent-directory is not an atypical use case.
I'm not sure how popular this is, but breaking it might be bad.

Maybe this is icky, maybe this isn't even worth it, but could we restrict JavaScript files from disk to certain file endings?
What's your take, Dan?

Flags: needinfo?(dveditz)

could we restrict JavaScript files from disk to certain file endings?

That's what I was talking about in the previous comment, and we have no data on what we'd break. I'd love to do something like this, but I'm also fearful of "this works in Chrome, Firefox is broken". Also worried about getting in the way of people inventing new sub-types. Once upon a time .json and .mjs weren't standard javascript extensions (not to mention our internal .jsm). Will someone invent .jsc as a convention to hold JavaScript classes? There's no way for devs to "fix" a new extension if we break this for local files, unlike the ability to add a Content-Type: header on a server for a new extension. On the other hand this would push more people to develop against localhost servers instead of raw file:// access which would be a good thing!

Our restrictions on Web mime type blocking are pretty loose, too. See bug 1333995 for the desire to do more there.

Note that the included file must parse as JavaScript for this to work.

  • if you add a # comment line to the file this will fail
  • if you don't quote the values (common in the /etc/environment documentation I've seen) this will fail

There are so many files this trick doesn't work for that it might almost be easier and less risky to fix this by specifically excluding /etc/environment!

Adversarial inclusion of local data into a downloaded file is a known concern so this doesn't need to be a hidden bug. For example, Google's 2008 Browser Security Handbook says:

Lastly, tags such as <SCRIPT> or <LINK REL="stylesheet" HREF="..."> could be used to read back certain constrained formats of local files from the disk, and access the data from within cross-domain scripts. Although no particularly useful and universal attacks of this type were demonstrated, this posed a potential risk.

In my testing chromium browsers behave exactly the same as Firefox in this test.

Group: dom-core-security
Flags: needinfo?(dveditz)
Summary: file URLs should not be able to load other files as script → file URLs should not be able to load other files as script unless they have an allowed extension (which should be user-configurable)
Type: defect → enhancement
Whiteboard: [reporter-external] [client-bounty-form] [verif?] → [domsecurity-backlog2][reporter-external] [client-bounty-form] [verif?]
Flags: sec-bounty? → sec-bounty-
Component: DOM: Security → DOM: Core & HTML

This was fixed in FIrefox 102 (current nightly) as part of bug 1760024

Status: NEW → RESOLVED
Closed: 2 years ago
Resolution: --- → FIXED
Assignee: nobody → tschuster
Target Milestone: --- → 102 Branch

Except it was disabled, and now lives in Bug 1775377

Whiteboard: [domsecurity-backlog2][reporter-external] [client-bounty-form] [verif?] → [domsecurity-backlog2][reporter-external] [client-bounty-form] [verif?][adv-main102-]
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: