Skip to content
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

Security considerations #22

Open
robertmuehsig opened this issue Oct 29, 2017 · 33 comments
Open

Security considerations #22

robertmuehsig opened this issue Oct 29, 2017 · 33 comments

Comments

@robertmuehsig
Copy link
Collaborator

Twitter discussion - currently we launch a plain webserver on localhost. Maybe we could avoid to launch a "real" webserver at all, see here:

https://twitter.com/robert0muehsig/status/924741177525587968

@damianh
Copy link

damianh commented Oct 29, 2017

In a previous incarnation of sort of the same thing (but windows only), it was possible to hook into chrome, register a scheme and have the handler take the request and directly invoke it against the pipeline.

https://github.com/eVisionSoftware/Harley/blob/master/src/Harley.UI/MainWindow.xaml.cs#L23
https://github.com/eVisionSoftware/Harley/blob/master/src/Harley.UI/Owin/OwinSchemeHandlerFactory.cs#L44

I'd be really surprised if there wasn't an equivalent hook in Electron.

The hard part is probably hosting the .net code / clr in the same process. Definitely done elsewhere, but beyond my knowledge at this point.

Wondering if edge.js has anything useful to lift?

@damianh
Copy link

damianh commented Oct 29, 2017

Well hello

https://github.com/tjanczuk/edge/blob/master/src/CoreCLREmbedding/coreclrembedding.cpp

@robertmuehsig
Copy link
Collaborator Author

Nice one - I guess currently our priorities would be to work on some basics, like easier debugging support or actual better build support (Icons for the produced app etc.), but I'm really interested in doing this 👍 (or if you have some sparetime - just sent a PR 😃 )

@ghost
Copy link

ghost commented Oct 30, 2017

A big step.
Hosting the .net code / clr in the same process is a great feature.

@raffaeler
Copy link

raffaeler commented Oct 30, 2017

My xcore plugin for nodejs can smoothly call any netstandard assembly from nodejs (even async stuff) [in-proc of course] without having to do nothing for the interop (I do generate the required code on the fly) and allows to call almost any method/property/indexer/event/ctor.
Could this be of any help?

@robertmuehsig
Copy link
Collaborator Author

Sure - do you have a GitHub Repo for your code?

@raffaeler
Copy link

raffaeler commented Oct 30, 2017

The repo just contains the user guide and a couple of videos explaining how it works, but no sources yet.
https://github.com/raffaeler/xcore

I published the plugin here:
https://www.npmjs.com/xcorenode

There are few things that are worth to say:

  1. I am going to change the C++ part heavily in order to adopt N-API which is the nodejs API which should not require to recompile the plugin for each nodejs version
  2. I could use it from the standard Electron but in certain cases Electron crashes. Looking with windbg the crash, it does not depend on my plugin but noone (in chat or on github) from Electron helped me to understand the issue.
  3. I am also improving the perf in the netcore side of the plugin
  4. Part of the plugin is already x-plat (like for example loading coreclr) but I still have to adjust few other things to make it entirely work on linux.

If you have other questions, please let me know

@robertmuehsig
Copy link
Collaborator Author

@raffaeler Is XCore/XCoreNode similar to Edge.js but works with .NET Core?

@raffaeler
Copy link

I like to say that is more than that.
Edge.JS impose a fixed signature for the method to be called while xcorenode leave the .net developer free to shape the class at her will. Also, Edge.JS limit to methods while I allow ctos/props/methods/events, even with overloads (that were pretty difficult to implement).
The setup is also simpler. When I initially tried to use Edge.js, I had several troubles.
Instead I opted for a "self-contained deployment" so that all the required .net binaries are available and part of the plugin.
You can take a look to the npm package javascript examples to see the supported features.

Anyway, Edge.js is more mature and targets more than just .net interop, therefore please don't take my words as a critic towards Edge.js.

@yoDon
Copy link
Contributor

yoDon commented Nov 8, 2017

I like the idea of trying to internalize the webserver but it would be great to maintain the option of exposing the webserver when desired (I'm working on a project where I absolutely do want the webserver reachable from other processes running on the machine)

@GregorBiswanger
Copy link
Member

I have an idea with an own web proxy, which can not listen with Fiddler or an other HTTP Debugger.

The next idea is to allow only requests from electrons chromium browser.. It's not the best and I need help to create the web proxy with .net core..

We can give an additional option to deactivate some new security parts...

@raffaeler
Copy link

@GregorBiswanger I don't get your goal.
If you want to disable people sniffing the page, it's useless. I wrote a driver that can capture even localhost (which is "short-circuited" and is not processed from the whole network stack).
From a security perspective, once you are admin of the local machine, the game is over.

@GregorBiswanger
Copy link
Member

@raffaeler Yes, that is true. But every Electron application and local desktop application is not secure.. (reverse engineering etc.).. I think this steps are important to have a little better security.. protection of kiddy crackers :)

That is only an idea.. at the end the community should decide too..

I'm happy about other ideas too...

@raffaeler
Copy link

@GregorBiswanger just use https for internal communication then.
Again, you can decrypt the channel if you know how to retrieve the private key of the certificate but there will always be a way to sniff what the process is doing.
This is no different than any other desktop app. You can use spy++, windbg, APImon, or whatever else tool to watch the process activity in detail.
And even UWP is no different, sandboxes are done to avoid exiting the sandbox, but you can easily inject code there ... this is one of my demos ;-)

@GregorBiswanger
Copy link
Member

@raffaeler yeah.. thats right.. and the problem with certificate is, it expires..

The common question here is.. should we invest to the lightweight security implementations? (proxy, https etc.)

@raffaeler
Copy link

@GregorBiswanger you can create a self-signed lasting 100 years :)
From a security perspective you should just use the services offered from the OS.
Tokens, integrity levels and ACLs are the most common tools to avoid major issues from the other processes.
But once you run as admin on the box, the game is over :)

@yoDon
Copy link
Contributor

yoDon commented Nov 15, 2017

At the risk of proposing a "big idea" change, if your front end is a so-called single page app that gets delivered to the browser as a single chunk of HTML and a single bundle.js, then Electron's built-in Ipc functions means you can get all the benefits of running C# on the server without actually needing to run or expose ASPNET on the C# side.

The React sample I made (https://github.com/yoDon/Electron.NET-React-Typescript-MobX) maintains the full ASPNET MVC server in case someone wants to use the MVC capabilities, but it doesn't actually use any of it even while maintaining full C# state and functionality to back up the app. I added one class in /Ipc/Register.cs that registers all the Ipc routes. The register function is called by the ElectronBootstrap() function which is part of Configure(...) in Startup.cs. End result is I have the full Javascript/Typescript frontend UI experience and the full C# backend experience and no actual ASPNET functionality being used or needed anywhere in the process.

Like I said, that's a pretty "big idea" shift in how Electron.NET is used, but I think it's (a) more secure because it doesn't expose any ports and (b) the "right" way to do this sort of single-page application, without needing to do a ton of server work to regenerate all the static HTML repeatedly. React (and libraries like it) basically solved that problem for us. Build the HTML and bundle.js in advance, load it into the browser/renderer, and then everything after that is just exchanging function calls and json blobs with the server, which is what Ipc was built for.

Note I'm not proposing anything that would break compatibility with ASPNET (as I said, my sample maintains the full ASPNET stack and even loads an index.cshtml needlessly on launch just to prove it maintains the compatibility, even though it doesn't need it). If you really need ASPNET, use it, but I think for a very large numbers of use cases Ipc will handle 100% of what ASPNET would have been used for, without exposing any ports or enlarging the size and perf cost of the delivered applications.

UPDATE: We should confirm that ASPNET isn't being used behind the scenes to serve up my /wwwroot/index.html and /wwwroot/bundle.js files. That's a pretty tiny amount of surface area, and is stuff that the underlying Electron tech can clearly easily handle, but I'm realizing I haven't actually checked whether it's Electron or ASPNET that's handling serving up those two files at present.

@robertmuehsig
Copy link
Collaborator Author

AFAIK this line makes sure that wwwroot is exposed to Electron, so you make use of ASP.NET.

Even if we don't expose a ASP.NET Core Service to Electron, we still need the IPC communication going on, right?

@yoDon
Copy link
Contributor

yoDon commented Nov 15, 2017

Definitely need the IPC. When I first started looking at all this, I figured wtf is this IPC thing, I want "real" tech like SignalR, but then as I better understood what what going on I realized that IPC really is the right way to communicate between the two processes because it's a low-level direct pipe that's not exposed to the rest of the OS.

The way you have IPC and hosting of dot net integrated into Electron.NET is the magic that's the key to all this wonderful goodness.

@robertmuehsig
Copy link
Collaborator Author

robertmuehsig commented Nov 15, 2017

Wild idea to skip the ASP.NET stuff completly (at least for the "builded" app) : It would be possible to xcopy the wwwroot files to the electron dir, which will be packed, then we just need to boot up a .net core console application with the IPC stuff for the "backend".

Development/debugging might be "harder", but could work.

@yoDon
Copy link
Contributor

yoDon commented Nov 15, 2017

I'm pretty sure that Electron already supports hot reloading of the HTML/JS, so if you tweak the source JS files it would automatically do the transpiling/webpacking/loading/refreshing etc on the fly as you type in your editor. It's pretty slick stuff.

@yoDon
Copy link
Contributor

yoDon commented Nov 15, 2017

<- Technically the "it" that I referred to about would be webpack that's watching the filesystem and regenerating the code and such (I have all that running now in my boilerplate, the /wwwroot/bundle.js files will auto regenerate as you change the source files, but my HTML isn't configured yet to hot-load the updated bundle.js files (I think that's a pretty straight forward thing to do on the npm/HTML side, I just haven't gotten to it yet)

@robertmuehsig
Copy link
Collaborator Author

Mhhh... so you suggest we should just host the IPC stuff inside the actual .NET Core process?

@yoDon
Copy link
Contributor

yoDon commented Nov 15, 2017

I'm WAY less knowledgable about the dotnet core internals than you guys are but I think that's what I'm suggesting. Then you'd still be able to host ASPNET if you wanted to but it wouldn't be a required part of the process. You'd just need some way to tell Electron to host the files that are currently thought of as the /wwwroot contents if you were to make ASPNET optional.

@ghost
Copy link

ghost commented Nov 16, 2017

@yoDon HI
I saw this line

_socket = IO.Socket("http://localhost:" + BridgeSettings.SocketPort);

and this
BridgeConnector.Socket.On(channel, (args) =>

It seem like ElectronNET.API.IpcMain base on socket. It isn't realy ipc.
Am I right?

@yoDon
Copy link
Contributor

yoDon commented Nov 16, 2017

@konding all I know is the "IPC" terminology comes from how atom and Electron talk about their code. I'm not sure if the ElectronNET bits are implemented the same way as the base Electron IPC but @robertmuehsig or @GregorBiswanger probably know

@robertmuehsig
Copy link
Collaborator Author

Mhh... the communication path is described here. Our Electron.NET talks via this Socket to the Electron stuff.

I'm not sure what the definition of IPC is, but we use http as the channel. At work we are using named pipes to do IPC, but we just run on Windows. What is your definition of IPC @konding ?

@ghost
Copy link

ghost commented Nov 16, 2017

My understanding is two objects communicate with each other in the same process. @robertmuehsig

@raffaeler
Copy link

FYI I could solve the issues of my plugin with Electron. It was not a real bug, but both me and Electron used a "slot" so each of us was overwriting the other.
Anyway, I could successfully run C# code inside the renderer process. I still have no public releases.
BTW, if anyone of you is at the next mvp summit, I will be there and we can chat about it.

@robertmuehsig
Copy link
Collaborator Author

@raffaeler Then we shall meet at the summit :) @GregorBiswanger

@raffaeler
Copy link

You can bet! :) My handle here is the same on twitter.

@nathanwienand
Copy link

I have added the build parameter to /p:PublishSingleFile true in my recent PR.
I have a version of blazor webassembly, with host running in Electron.NET, bundled as single .exe file.

The only code exposed is .wasm file, so disassembly is not as easy as dropping DLL's into ILSpy or DotNetPeek anymore.
Also the app doesn't ship with any dll's this way. just a single .exe

@domialex
Copy link

domialex commented Feb 23, 2021

If some people are strictly concerned about security, here's something I did for my project: domialex/Sidekick@6a9f7bf

Important parts are the await browserWindow.WebContents.Session.Cookies.SetAsync(electronCookieProtection.Cookie); and the ElectronCookieProtectionMiddleware.

I just added a cookie with a Guid generated on startup to the BrowserWindow, then a middleware that verifies it on every request. Works perfectly.

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

No branches or pull requests

7 participants