How to create sandbox in C# for external process?
As sandbox I understand an environment for process I start from C#, that stop that process from interfering with anything else - kernel, system variables, system configuration, memory, registry, disk, hardware, location other than starting place and so on.
I want place executable in one place and be sure that this place is only place that can be changed by this process. Additionally, executable can be written in C, C++, C# and etc.
If you only wanted to run managed code, it's relatively easy to create a Sandbox environment using an AppDomain w/ a restricted permission set:
PermissionSet ps = new PermissionSet(PermissionState.None);
// ps.AddPermission(new System.Security.Permissions.*); // Add Whatever Permissions you want to grant here
AppDomainSetup setup = new AppDomainSetup();
Evidence ev = new Evidence();
AppDomain sandbox = AppDomain.CreateDomain("Sandbox",
ev,
setup,
ps);
sandbox.ExecuteAssembly("ManagedAssembly.exe");
But as soon as you open the door to unmanaged/unsafe code all bets are off, and it becomes very difficult to secure 3rd party code. As has been mentioned, you basically have to create a shim between the executing code and the OS to limit what it can do, unless it is sufficient to run it as a restricted user and rely on ACLs/UAC alone to protect you.
NOTE: that code sample is not a working sample, just an idea of what the code would look like. Some finagling w/ Evidence and AppDomainSetup will probably be necessary, and you should certainly research/test the heck out of it considering the security implications. Here's a good article on the topic: http://msdn.microsoft.com/en-us/magazine/cc163701.aspx
Using Sandboxie as an example of what I think you are wanting to achieve to some extent. IMHO, you will not be able to do this in pure managed code.
If you want to be able to limit what actions and the effect of an application regardless of if it is a managed or native or even Java application. The implication is that you will need to monitor every action taken by the application and take the approriate action to ensure that it does not impact your system. The appropriate action could mean that you redirect the application write to an alternate location on the disk, write a virtualized registry so that the real registry is not impacted etc. etc. All this will require a lot of low level work that managed code does not provide today.
Note I said pure managed code, you could of course use Interop Services etc. to take advantage of unmanaged implementation of certain areas of code, or you could use managed C++. However, depending on the exact details of what you want your sandbox to do you will probably need to implementa a kernel mode driver to ensure that you can sufficiently virtualize the environment for the sandboxed user mode applications.
Related
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.
How to create sandbox in C# for external process?
As sandbox I understand an environment for process I start from C#, that stop that process from interfering with anything else - kernel, system variables, system configuration, memory, registry, disk, hardware, location other than starting place and so on.
I want place executable in one place and be sure that this place is only place that can be changed by this process. Additionally, executable can be written in C, C++, C# and etc.
If you only wanted to run managed code, it's relatively easy to create a Sandbox environment using an AppDomain w/ a restricted permission set:
PermissionSet ps = new PermissionSet(PermissionState.None);
// ps.AddPermission(new System.Security.Permissions.*); // Add Whatever Permissions you want to grant here
AppDomainSetup setup = new AppDomainSetup();
Evidence ev = new Evidence();
AppDomain sandbox = AppDomain.CreateDomain("Sandbox",
ev,
setup,
ps);
sandbox.ExecuteAssembly("ManagedAssembly.exe");
But as soon as you open the door to unmanaged/unsafe code all bets are off, and it becomes very difficult to secure 3rd party code. As has been mentioned, you basically have to create a shim between the executing code and the OS to limit what it can do, unless it is sufficient to run it as a restricted user and rely on ACLs/UAC alone to protect you.
NOTE: that code sample is not a working sample, just an idea of what the code would look like. Some finagling w/ Evidence and AppDomainSetup will probably be necessary, and you should certainly research/test the heck out of it considering the security implications. Here's a good article on the topic: http://msdn.microsoft.com/en-us/magazine/cc163701.aspx
Using Sandboxie as an example of what I think you are wanting to achieve to some extent. IMHO, you will not be able to do this in pure managed code.
If you want to be able to limit what actions and the effect of an application regardless of if it is a managed or native or even Java application. The implication is that you will need to monitor every action taken by the application and take the approriate action to ensure that it does not impact your system. The appropriate action could mean that you redirect the application write to an alternate location on the disk, write a virtualized registry so that the real registry is not impacted etc. etc. All this will require a lot of low level work that managed code does not provide today.
Note I said pure managed code, you could of course use Interop Services etc. to take advantage of unmanaged implementation of certain areas of code, or you could use managed C++. However, depending on the exact details of what you want your sandbox to do you will probably need to implementa a kernel mode driver to ensure that you can sufficiently virtualize the environment for the sandboxed user mode applications.
So I need to run dynamically compiled untrusted code in a new process. I found how to do that in a new AppDomain (http://msdn.microsoft.com/en-us/library/bb763046.aspx) but not new process. Is it possible to do?
The reason I need new process is because it is easier to capture standard output, see memory and cpu consumption and terminate it.
The end goal is to write online C# compiler.
AppDomains are a way to isolate .NET code in a system. Processes are an operating system mechanism for isolation. To some degree you will give up the niceties of .NET code and have to manually manage the transfer of data between processes.
Check out the Process class. It sounds like you either need to compile your code to a .exe, or create a host .exe in .NET that loads your code. The latter seems better as you can just write the host once and then write standard communication code with that host.
You don't provide a lot of information on your end goals but recent versions of .NET provide various plug-in APIs that might be worth a quick look.
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.).
Imagine an untrusted application (plugin) that reads from the standard input and writes to the standard output.
How to get the output returned for the specified input by this application preventing any side effects?
For example, if application deletes file on a disk, it should be detected and this attempt should be canceled.
It's some kind of wrapper application. Is it possible to build it?
Less complicated task is too interesting: make this wrapper using .NET (both host and client are written in .NET language).
Safest way would be to load that plugin into a separate AppDomain which you configure with the security evidence for the requirements you have.
When you create an AppDomain, you can specify exactly the kinds of things code can do in this sandbox. Code that runs there is restricted to the limits you set. But this process can be confusing the first time you do it and may still leave you open to vulnerabilities.
Using AppDomains to isolate assemblies is an interesting process. You'd think you load your plugins into the other AppDomain then use them via proxies in your AppDomain, but its the other way around. They need to use your proxies in their AppDomain. If you fail to understand and do this right, you'll end up loading your plugin code within your main AppDomain and executing it there instead of in the restricted domain. There are lots of gotchas that you'll get bit by (subscribing to events has some interesting side effects) if you don't do things correctly.
I'd suggest prototyping, brush up on the AppDomain chapter in CLR Via C#, and read as much as you can on the subject.
Here's a test app I made to investigate cross-appdomain events.
http://cid-f8be9de57b85cc35.skydrive.live.com/self.aspx/Public/appdomainevents.rar