Sandboxing is a technique used to restrict the resources that an application can access and is generally used to run untrusted code.
An example of a sandboxed environment is a Virtual Machine (VM), which hosts an entire operating system; this is useful for running untrusted code, but can be a bit too much overhead when, instead of needing to sandbox the entire operating system, we only need to sandbox a runtime or a single application. Fortunately, .NET does let us place restrictions on processes in the form of an AppDomain.
Microsoft's definition of an AppDomain is "an isolated environment where applications execute". Perfect. Now how do we work with it?
First, let's define a use-case for creating a sandbox and we'll go from there.
Imagine that you are writing an application that loads plugins written in C# . These plugins have access to the same resources that the hosting application does, but that is a bit too control much considering that the plugin:
* Is untrusted
* Has access to the registry
* Has full access to the file system
* Has access to network resources
* etc.
Now, lets imagine that the hosting application needs and utilizes all of these resources and the purpose of each plugin is only to run a calculation and display output from that to an output stream. It can access only the files that it has created and must be completely isolated from other plugins and their data.
So, we need to ensure that each plugin has restrictions on the files it can access. In short, each plugin must:
* Only be able to access a directory assigned to the process
* Be able to only modify files inside that directory
* Not be able to access files created by other plugins
* Be denied all other resources aside from limited filesystem access.
We also need to take into account that since each plugin is untrusted, we need to set boundaries on memory and hard disk IO. We cannot have this plugin consume excessive memory and we need to ensure that the application can't consume all of our disk space maliciously. Fortunately, there exists a Win32 method for doing this called Job Objects. To access these in C#, you will need to use a bit of P/Invoke to utilize this feature, but it's not very difficult to say the least.
Combining these two ideas, one should be able to place limits on I/O as well as virtual memory usage. I recently began working on a simple library to combine these two into a unified basic sandbox process with time being the only thing holding back a release. I will share whatever code I can when I get the opportunity to do so, preferrably in the form of a usable API.
No comments:
Post a Comment