Limiting external process resources programmatically - c#

I'm developing a .NET application, which have a 3rd party plugins. These plugins comes as EXE files, which works with application APIs and data.
Due to security concerns, I would like to be able "sandbox" them, when they're launched through my application. Especially, the most important is to be able to limit access to the drives or directories of filesystem.
Is there any way to do this through AppDomain? Or in any other way?
Also some external plugins may not be written in managed code as my software exposes APIs to COM, but it is possible to drop non .NET plugin support. The more important thing for us is to sandbox those plugins.
Any way to solve this is appreciated.

Given that you need to do this for a process that's not (necessarily) entirely based on .NET, AppDomains probably won't be adequate for the task.
I'd consider running the processing inside a Windows Job Object. This lets you set up a sandbox that limits the process' use of things like the CPU and memory.
Access to the file system is already handled based on user accounts using Discretionary Access Control Lists (DACLs). To limit access to a few specific parts of the file system, set up an account to use to run the sandboxed jobs, and set up access-allowed ACEs for the parts of the file system they're allowed to use. If you need to support more than one user running sandboxed jobs, you might want to set up a user group for the sandboxed jobs, and associate the ACEs with the group instead of the individual users.

Related

Starting a .NET process within an AppDomain

The title of my question might already give away the fact that I'm not sure about what I want, as it might not make sense.
For a project I want to be able to run executables within my application, while redirecting their standard in and out so that my application can communicate with them through those streams.
At the same time, I do not want to allow these executables to perform certain actions like use the network, or read/write outside of their own working directory (basically I only want to allow them to write and read from the standard in and out).
I read on different places on the internet that these permissions can be set with PermissionStates when creating an AppDomain in which you can then execute the executables. However, I did not find a way to then communicate with the executables through their standard in and out, which is essential. I can however do this when starting a new Process (Process.Start()), though then I cannot set boundaries as to what the executable is allowed to do.
My intuition tells me I should somehow execute the Process inside the AppDomain, so that the process kind of 'runs' in the domain, though I cannot see a way to directly do that.
A colleague of mine accomplished this by creating a proxy-application, which basically is another executable in which the AppDomain is created, in which the actual executable is executed. The proxy-application is then started by a Process in the main application. I think this is a cool idea, though I feel like I shouldn't need this step.
I could add some code containing what I've done so far creating a process and appdomain, though the question is pretty long already. I'll add it if you want me to.
The "proxy" application sounds like a very reasonable approach (given that you only ever want to run .NET assemblies).
You get the isolation of different processes which allows you to communicate via stdin/stdout and gives the additional robustness that the untrusted executable cannot crash your main application (which it could if it was running in an AppDomain inside your main application's process.
The proxy application would then setup a restricted AppDomain and execute the sandboxed code, similar to the approach described here:
How to: Run Partially Trusted Code in a Sandbox
In addition, you can make use of operation system level mechansims to reduce the attack surface of a process. This can be achieved e.g. by starting the proxy process with lowest integrity which removes write access to most resources (e.g. allow writing files only in AppData\LocalLow). See here for an example.
Of course, you need to consider whether this level of sandboxing is sufficient for you. Sandboxing, in general, is hard, and the level of isolation always will be to a certain degree only.

Is there a way to associate arbitrary data to a Windows Process?

I have many instances of a process I've written on a server. I'd like to associate some information with each process. In this specific case I'd like to store the "CurrentState" of the process - "RUNNING|DRAINING|STOPPING", but it would be useful for me to store a "Friendly Name" and so on.
I want to query this information from another "mother" process - this mother process will query the processes running and collate the data.
I've thought of a couple of different ways I could achieve this. For example I might open up a NetPipe to each process of interest and ask for the data, or have each process broadcast it's state regularly.
I was wondering: is there a way to store key value pair information against a process built into Windows itself? Is there an accepted pattern for doing this?
I control the source for the child processes and the mother process. They are written in C#, P/Invoking is fine. The operating system is Windows 2012 R2.
You can host WCF services that use named pipes:
http://msdn.microsoft.com/en-us/library/ms733769(v=vs.110).aspx
Based on some of your comments, it looks like you could also consider the System.AddIn (aka Managed AddIn Framework (MAF)) functionality to create, host, and communicate with Add-ins. MAF supports loading addins in your app domain, a separate app domain, or in a completely separate process. The downside with MAF is that it requires 5 DLLs to get started, but in doing that gives you a lot of flexibility with API compatibility as you version and change your pipeline.
If you're controlling the data from a Mother process, you can also use AppDomains to load your other processes and communicate via Marhsaled data such as a Status class, or use the AppDomains to Set and Get data.
Be aware that any Status data you transfer needs to either be a class which derives from the Marshaling class or be marked as Serializable. The reason for this is because AppDomains are treated in the OS the same as different processes, so they can't access each others memory an actually have to serialize data as if it were being passed through IPC.
Take a look at the .Net Process Class:
http://msdn.microsoft.com/en-us/library/system.diagnostics.process(v=vs.110).aspx
You can use it to get all running processes, start a process, get the processes unique Id, and be alerted when the process exits. This should give you everything you need to track processes.
Children can call Process.GetCurrentProcess to get their own process id, then make a call to the "mother" process to associate arbitrary data about itself.

Apply patch to COM+ Application safely

We've some COM+ Application composed of several DLLs containing several serviced components each (written in C#), running over Windows Server 2003/2008R2 operating systems.
Under certain circumstances (that we try to avoid as much as possible) we are obliged to apply a patch to correct a bug. To accomplish this what we currently do is (of course assuming that we have all the stuff needed on the destination server):
Disable the COM+ App.
Shutdown the COM+ App.
Un-register the DLLs involved to be replaced.
Replace the DLLs.
Register again the DLLs involved.
Enable the COM+ App.
There is no problem with the mentioned steps above, we built a small application for managing the COM+ Application Catalog programatically, through the command line, so this way we can update some DLLs and bring the serviced components to live in approx. 2 secs... It is not too much for us and we can afford this (offline) time, but I would like to improve and automatize entirely the process by writing a patching tool.
What I'm trying to figure out is:
How could I know that all the serviced components of my COM+ Application have finished their work (all requests/calls have been finished) so that I can proceed SAFELY to point 2 ?
More in details, is there any library that I could use to get the status of the Serviced Components of a certain COM+ Application ?
NOTE: if you are used to work with dcomcnfg, the data I would need to gain access is the same that you see if you expand the COM+ Application folder under Console Root\Computers\My Computer\<MyComPlusApp>, then you expand the folder Components and go to menu View and select Status menu item. Windows of course is able to know the status of every COM+ Serviced Component a display it in the screen, so that's exactly the data what I would need to have access to.
How could I know that all the serviced components of my COM+
Application have finished their work (all requests/calls have been
finished) so that I can proceed SAFELY to point 2 ?
You could use the COM+ Instrumentation Interfaces or COM+ Tracking to receive information about your components.
More in details, is there any library that I could use to get the
status of the Serviced Components of a certain COM+ Application ?
The IGetAppTrackerData interface should let you get the information you need.
Some caveats: Don't forget that you need to be careful when shutting down the application since the component could not be in call but before shutdown another call comes in that is serviced. Also, in my experience using the COM+ API can get messy and the documentation is sometimes lacking (especially in terms of examples).
It seems like it could be a bit of work to save 2 seconds. :)

Creating COM Component in .NET to override IE functionality (custom download manager)

I have to create a custom download manager that will replace a standard download manager in Internet Explorer. After googling I've learned that I have to create a COM component that implements the IDownloadManager interface.
As far as I understand I have to create a dll, generate guid for it and register it using regasm.exe utility, and then add specific entry in windows registry for IE.
I have a few questions:
I want my program to be an exe and I want to be able to run it manualy and add url to it as well as run it by IE after clicking on a downloadable link.
Although I would prefer to have a single executable, I think to achieve this i have to create dll and exe, and from dll i should check whether the exe is running (by window id) and run if it isn't and communicate with it somehow. Is this correct approach?
I want to share my program with other users, and i don't want them to register COM manually. Is it possible to do it from the code? Or perhaps I should create an installer (which I would like to avoid)?
I'll start with a WARNING: Do not create a .Net components that will be loaded in IE. Ask yourself the question "What would happen if another app does the same, and it uses different version of the CLR?". IE does not guarantee any order of loading the different COM components it needs, so there's no guarantee that your version of the CLR will be loaded in the process by the time IE calls you.
Now onto your problem. There are several issue with your scenario:
.Net does not support creating out-of-proc COM components natively. Yes, it is possible to create one by doing bunch of hacks and manual registration; however, it is not a simple task and requires deep knowledge of how COM works;
with the above in mind, your option is really to create a .Net DLL and use the ComVisible attribute to expose the classes you need to COM. As you mentioned it, you will need to register it using RegAsm.exe, for IE to be able to use it;
since you want the main functionality of your download manager to be in a standalone executable, you will have to use a .Net supported cross-process communication mechanism. .Net Remoting is likely the easiest way to implement it, and should for the most part meet your requirements. The alternative is to implement the download functionality in-proc. However, beside the consideration that you now could easily hose the IE process, if you are not careful to listen to its quit notification (which require a lot more work by itself), there's also the whole enchilada with the IE7+ protected mode, which severely limits what your in-proc code can do (limited file access, registry access, Windows APIs and other limitations);
there are certain complications arising from the IE8 and IE9 process model. Besides the top frame process, IE8/9 create a pool of processes and load-balance the tabs into these. I don't know which process will try to create your COM component and wheter it's going to be one per tab or per process or for the whole IE session (which spans multiple processes), so you have to be prepared that you might have multiple instances in multiple processes running concurrently. If this is the case, you will have to figure out how to ensure that the communication between the in-proc COM component and the executable is not serialized one instance at a time, or you might affect the browsing experience for the user. (A simple scenario would be a page with multiple download links and the user right-clicking on each link and selecting Open in new tab, thus launching multiple downloads in several tabs at once);
even if there is one instance per IE session, elevated IE instances run in a separate session from the regular user IE instances for security reasons. There's the interesting complication that your .Net Remoting call from the in-proc COM component in the elevated IE session will result in a second copy of your executable being launched also elevated. Thus, your download manager will have to be prepared that there might be two processes accessing the same download queue;
starting with IE7, IE protected mode (the default) will intercept any calls that result in starting a new process and show a dialog to the user. The only way to avoid this would be to register a silent IE elevation policy for your process. The elevation policies are registered in HKEY_LOCAL_MACHINE, which means that you will need an installer, or at least a simple script for the users to run as administrator;
even if you decide against the elevation policy and to live with the bad experience of this dialog, to register your download manager with IE, you still will have to write to the HKEY_LOCAL_MACHINE registry hive, otherwise IE will not know of it and won't use it. In other words, you still need some kind of installer or a deployment script;
IE is fairly aggressive in measuring the performance of the code that runs on the UI thread and in terminating background threads when exiting the process. So whatever functionality you have in the in-proc component, you will have to balance between being as fast as possible on the UI thread (which means less work or you'll impact the user experience) and doing work on the background threads (which means be prepared you might be killed without notification at any moment);
I think this list covers the main issues you will have to solve. The biggest problem you will encounter is that a lot of the specifics around IE process model are not well documented on MSDN, and there are almost no examples of implementing this scenario in managed code (and of those that exist, most are old and are not updated for IE8/IE9, and some even won't work in IE7).

I am forced to use Process but I need AppDomain-like security policies. How to do that?

alt text http://img185.imageshack.us/img185/2080/mydiagram.png
Maxima.exe is a Computer Algebra System built as a native code rather than a managed code.
MyService works as a socket server, it will instantiate a new process of Maxima for each browser submitting mathematics expression to Web Server.
I cannot use AppDomain here because Maxima is a native code. However I want security policies provided by AppDomain such as restriction to write data on file system.
My question is, how can I get the AppDomain-like security policies when I instantiate Maxima in a process rather than in an AppDomain?
Since Maxima.exe is a native executable, the only security policies you can apply are those supported by the base Windows operating system. Unfortunately, that means your options are pretty limited: the only really useful thing you can do is run Maxima.exe in the context of a user account with limited privileges. When it comes to disallowing write access to most of your system, that should be sufficient, though.
The dated-but-still-useful article Safe Impersonation With Whidbey shows how to run a worker function in the context of another user account: you would then start Maxima.exe from that worker function.
Running as a limited user will of course still allow various Maxima.exe instances to interfere with each other to a certain degree (i.e. overwrite files created in the instance working directory). Starting each instance with a unique, randomly-created working directory (e.g. based on a GUID) may offer sufficient security for your purposes: if not, you may actually need to create distinct user accounts for each instance (or at least have a pool of user accounts for that purpose).
In the end, it all comes down to "how would I solve my security problem using Windows base-only features", and unfortunately you won't have access to the much nicer .NET security features or the facilities found on non-Windows platforms (jails, systrace, etc.).

Categories