Bug 479943 (CVE-2009-1839)

Restrictions on file-URL-to-file-URL scripting don't appear to be working properly

RESOLVED FIXED

Status

()

Core
Security: CAPS
RESOLVED FIXED
9 years ago
8 years ago

People

(Reporter: Adam Barth, Assigned: bz)

Tracking

(Depends on: 1 bug, {fixed1.9.1, verified1.9.0.11})

unspecified
fixed1.9.1, verified1.9.0.11
Points:
---
Bug Flags:
wanted1.9.0.x +
wanted1.8.1.x -
in-testsuite ?

Firefox Tracking Flags

(Not tracked)

Details

(Whiteboard: [sg:moderate])

Attachments

(3 attachments)

(Reporter)

Description

9 years ago
Collin and I were experimenting with the restrictions on file-URL-to-file-URL scripting and found some strange behavior.  Imagine you have the following files on your local file system:

/foo/bar/target.html (contains some text)
/foo/bar/child/index.html (contains an iframe to /foo/bar/target.html)

Steps to reproduce:

1) Type "file:///foo/bar/child/index.html" in the location bar and hit enter.
2) Notice that /foo/bar/child/index.html cannot access /foo/bar/target.html
3) Type "file:///foo/bar/target.html" in the location bar and hit enter.
4) Type "file:///foo/bar/child/index.html" in the location bar and hit enter.
5) Notice that /foo/bar/child/index.html *can* access /foo/bar/target.html

Bizarre, no?
(Reporter)

Comment 1

9 years ago
Created attachment 363851 [details]
part one of test case
(Reporter)

Comment 2

9 years ago
Created attachment 363852 [details]
part two of test case
I'm seeing different behavior than in your STR:

> 1) Type "file:///foo/bar/child/index.html" in the location bar and hit enter.
> 2) Notice that /foo/bar/child/index.html cannot access /foo/bar/target.html

I have /home/brandon/Desktop/child/index.html and
/home/brandon/Desktop/target.html

and when I load child/index.html the contents of target.html are visible in the iframe.  I cleared my cache before loading the child page.

> 3) Type "file:///foo/bar/target.html" in the location bar and hit enter.
> 4) Type "file:///foo/bar/child/index.html" in the location bar and hit enter.
> 5) Notice that /foo/bar/child/index.html *can* access /foo/bar/target.html

It could see target.html before, but I can see why that would be strange if you weren't seeing the parent in step 1.  Can someone else confirm the behavior?
(Reporter)

Comment 4

9 years ago
> and when I load child/index.html the contents of target.html are visible in the
> iframe.

Sorry, my description wasn't clear.  Try clicking the button that says "Go!".  The first time through, the outer page can read the contents of the inner page (its HTML shows up in the alert) but the second time through it can't.
> Bizarre, no?

Bizarre yes, but as intended for better or worse.

The first efforts at tightening up the same-origin policy ("same directory only") broke too many real-world use cases (e.g. on-disk reference material). Allowing parents to reach into sub-directories but not vice-versa created asymmetric permission checks which isn't a good idea in our codebase (bug 402983) and still managed to break a few real-world cases that have wide distribution such as Sun's Java documentation. Making it blindly symmetric meant a file could open a guessed root document (C:\boot.ini on windows?), and then inject script into that document that could spider down elsewhere making all the checks moot.

The current behavior is that files are only same-origin only if they have exactly the same principal, but when a file opens another file in the same directory or a subdirectory it bestows it's own principal on that file. If a file opens a file in a parent or sibling directory it gets its own principal, and the two cannot access each others content. This does lead to the odd order dependency you noted, where if the child is opened by the parent they access each other but if the parent is opened by the child they can't.

When opening a file the new file's location is compared against the principal of the opener and not the actual location (again, in an attempt to not break real-world documents). So if you have
    docs/parent.html
    docs/chap1/section1-1.html
    docs/chap2/section2-1.html
then if parent.html opens section1-1.html, either parent or section1-1 can open section2-1 and all three can interact.

In no case are files allowed to read the contents of a file: URI that is a directory listing, even a subdirectory listing, to prevent spidering.

I'm unhiding this bug because this behavior should be documented, and as written probably INVALID. However it is quirky enough that there might be unintended misbehaviors worth investigating.
Group: core-security
I would think that the principal shouldn't inherit across loads via the url bar.  This bug says that it does, right?
rehiding. Files opened via the URL bar should get a fresh start. Is that what Adam is saying?
Group: core-security
Whiteboard: [sg:investigate]
(Reporter)

Comment 8

9 years ago
(In reply to comment #7)
> rehiding. Files opened via the URL bar should get a fresh start. Is that what
> Adam is saying?

Yes.
Yeah, so nsDocShell::InternalLoad will use the current document's principal as the owner if no owner is provided and a file:, data:, or javascript: URI is being loaded, and DoURILoad will use the owner if loading a file URI if the owner passes the CheckMayLoad() check.

Is there a reason we're getting an owner in InternalLoad in the file case?  I thought location sets and link clicks always passed in an owner directly, no?
Whiteboard: [sg:investigate] → [sg:moderate]
Created attachment 369787 [details] [diff] [review]
Proposed fix

With this change we actually do pass the principal in for link clicks and form submission.  Subframe loads and location sets were already doing it.  This lets us remove the "inherit the owner" flag from this case, and to stop inheriting the owner for file:// URIs in all cases.

I did check that <a href="someOtherFile.html" target="_blank"> works to give the new page the same principal as the old one if the new page is in the same dir or a subdir.  We really need file:// mochitests.  :(
Assignee: dveditz → bzbarsky
Status: NEW → ASSIGNED
Attachment #369787 - Flags: superreview?(jst)
Attachment #369787 - Flags: review?(dveditz)

Updated

9 years ago
Attachment #369787 - Flags: superreview?(jst) → superreview+
Flags: blocking1.9.1?
Flags: blocking1.9.0.10?
Comment on attachment 369787 [details] [diff] [review]
Proposed fix

r=dveditz

I was waiting for a chance to test this, but for now I'll take bz's assurance that link navigation preserves the correct owner.
Attachment #369787 - Flags: review?(dveditz) → review+
Tested and it works as I'd expect.
Pushed http://hg.mozilla.org/mozilla-central/rev/354f5ac7485d

Tests will have to wait on bug 424484.
Status: ASSIGNED → RESOLVED
Last Resolved: 9 years ago
Depends on: 424484
Flags: in-testsuite?
Resolution: --- → FIXED
Comment on attachment 369787 [details] [diff] [review]
Proposed fix

We should take this on branches too.  This should be reasonably safe, I hope, but some baking is definitely needed.  The fact that we have no automated tests for this set of codepaths (nor a test infrastructure that could run them) makes things a bit worse than they should be.
Attachment #369787 - Flags: approval1.9.1?
Attachment #369787 - Flags: approval1.9.0.10?
Not blocking for now, please renom after baking. We'll look at the approval request anyway.
Flags: blocking1.9.0.10? → wanted1.9.0.x+
Whiteboard: [sg:moderate] → [sg:moderate] needs 1.9.1 approval and landing

Updated

9 years ago
Attachment #369787 - Flags: approval1.9.1? → approval1.9.1+
Comment on attachment 369787 [details] [diff] [review]
Proposed fix

Looks worth taking for 1.9.1.

Updated

9 years ago
Flags: blocking1.9.1? → blocking1.9.1-
Whiteboard: [sg:moderate] needs 1.9.1 approval and landing → [sg:moderate] needs 1.9.1 landing
Pushed http://hg.mozilla.org/releases/mozilla-1.9.1/rev/38b8a7bc6130
Flags: blocking1.9.1- → blocking1.9.1?
Keywords: fixed1.9.1
Whiteboard: [sg:moderate] needs 1.9.1 landing → [sg:moderate]
Flags: blocking1.9.1?
Comment on attachment 369787 [details] [diff] [review]
Proposed fix

Approved for 1.9.0.10, a=dveditz for release-drivers
Attachment #369787 - Flags: approval1.9.0.10? → approval1.9.0.10+
Checked into CVS.
Keywords: fixed1.9.0.10
I notice that I can no longer get the alert when I load the child directory case in Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.11pre) Gecko/2009051111 GranParadiso/3.0.11pre. I also see:

JavaScript error: file:///Users/abillings/Desktop/child/index.html, line 1: Permission denied to get property Window.document

Is this really enough to validate this fix?
Sounds like correct behavior, yes. Compare to the behavior before this patch landed.
I did compare the behavior. That's why I know about the alert. :-)

Following the steps in comment 0 with Firefox 3.0.10 and you will get the alert on the final step. Doing the same with 3.0.11, you do not get the alert.

Marking verified for 1.9.0.11.
Keywords: fixed1.9.0.11 → verified1.9.0.11
Irrelevant to the 1.8 branch where we let any file:/// document open any other file:/// document.
Flags: wanted1.8.1.x-
Group: core-security
Alias: CVE-2009-1839
You need to log in before you can comment on or make changes to this bug.