Running a .Net application in a sandbox - c#

Over the months, I've developed a personal tool that I'm using to compile C# 3.5 Xaml projects online. Basically, I'm compiling with the CodeDom compiler. I'm thinking about making it public, but the problem is that it is -very-very- easy to do anything on the server with this tool.
The reason I want to protect my server is because there's a 'Run' button to test and debug the app (in screenshot mode).
Is this possible to run an app in a sandbox - in other words, limiting memory access, hard drive access and BIOS access - without having to run it in a VM? Or should I just analyze every code, or 'disable' the Run mode?

Spin up an AppDomain, load assemblies in it, look for an interface you control, Activate up the implementing type, call your method. Just don't let any instances cross that AppDomain barrier (including exceptions!) that you don't 100% control.
Controlling the security policies for your external-code AppDomain is a bit much for a single answer, but you can check this link on MSDN or just search for "code access security msdn" to get details about how to secure this domain.
Edit: There are exceptions you cannot stop, so it is important to watch for them and record in some manner the assemblies that caused the exception so you will not load them again.
Also, it is always better to inject into this second AppDomain a type that you will then use to do all loading and execution. That way you are ensured that no type (that won't bring down your entire application) will cross any AppDomain boundary. I've found it is useful to define a type that extends MarshalByRefObject that you call methods on that executes insecure code in the second AppDomain. It should never return an unsealed type that isn't marked Serializable across the boundary, either as a method parameter or as a return type. As long as you can accomplish this you are 90% of the way there.

Related

Plugin architecture for .NET multi-agent simulation (runtime load/unload)

DESCRIPTION
I am currently designing an architecture for a C# multiagent simulation, where agent actions are driven by many modules in their "brain", which may read sensors, vote for an action or send messages/queries to other modules (all of this is implemented through the exchange of messages).
Of course, modules can have a state.
Modules run in parallel: they have an update method which consumes messages and queries, and perform some sort of computation. The update methods return iterators, and have multiple yields in their bodies, so that I can schedule modules cooperatively. I do not use a single thread for each module because I expect to have hundreds to thousands of modules for every agent, which would lead to a huge amount of RAM occupied by thread overhead.
I would like these modules to behave like runtime plugins, so that while the simulation is running I can add new module classes and rewrite/debug existing ones, without ever stopping the simulation process, and then use those classes to add and remove modules from the agents' brains, or just let existing modules change their behaviours due to new implementations of their methods.
POSSIBLE SOLUTIONS
I have come up with a number of possible solutions in the last few days, which all have something disappointing:
Compile my modules into DLLs, load each in a different AppDomain and then use AppDomain.CreateInstanceFromAndUnwrap() to instantiate the module, which I would then cast to some IModule interface, shared between my simulation and the modules (and implemented by each module class). The interface would expose just the SendMessage, the Update and a few other members, common to all modules.
The problem with this solution is that calls between AppDomains are much slower than direct calls (within the same AppDomain).
Also, I don't know the overhead of AppDomains, but I suppose that they are not free, so having thousands could become a problem.
Use some scripting language for the modules, while keeping C# for the underlying engine, so that there is no assembly loading/unloading. Instead, I would host an execution context for the scripting language for each module.
My main concern is that I do not know a scripting language which is big (as in 'python, lua, ruby, js are big, Autoit and Euphoria are not') fast, embeddable into .NET and allows step by step execution (which I need in order to perform cooperative scheduling of module execution).
Another concern about this is that I suppose I'd have to use a runtime context for each module, which in turn would have massive overhead.
Lastly, I suppose a scripting language would be probably slower than C#, which would reduce performance.
Avoid unloading of assemblies, instead renaming/versioning them somehow, so that I can have a ton of different versions, then just use the latest one for each type.
I'm not even sure this is possible (due to omonimous types and namespaces)
Even if possible, it would be very memory-inefficient.
Do a transparent restart of the simulation, which means pausing the simulation (and execution of the scheduler of brains/modules), serializing everything (including every module), exiting the simulation, recompiling the code, starting the simulation again, deserializing everything, catching any exception raised due to the changes I made to the class and resuming execution.
This is a lot of work, so I consider it my last resort.
Also, this whole process would be very slow at some point, depending on number of modules and their sizes, making it impractical
I could overcome this last problem (the whole process in solution 4 becoming slow), by mixing solutions 3 and 4, loading many many assemblies with some form of versioning and performing a restart to clean up the mess every now and then. Yet, I would prefer something that doesn't interrupt the whole simulation just because I made a small change in a module class.
ACTUAL QUESTION
So here is my question(s): is there any other solution? Did I miss any workaround to the problems of those I found?
For example, is there some scripting language for .NET which satisfies my needs (solution #2)? Is versioning possible, in the way I vaguely described it(Solution #3)?
Or even, more simply: is .NET the wrong platform for this project? (I'd like to stick with it because C# is my main language, but I could see myself doing this in Python or something alike if necessary)
Did you consider Managed Extensibility Framework?
I'm working in a simulation system that works in a very similar way, treating agent modules as plugins.
I created a Plugin Manager that handles every Domain loading related things, checking plugin validity in a dummy domain and then hotloading it in the engine domain.
Using AppDomain is where you can get the full control, and you can reduce process time by running your Plugin Manager's tasks in parallel.
AppDomains aren't cost free, but you can handle it using only two (or three if you need more isolation between validation and execution domains).
Once a plugin file is validated you can load it in the very main process at any time, creating a shadow copy in any domain's probing path (or in dynamic path if set) and targeting it instead of original file is useful to check versioning and updates.
Using a domain for validation and another to execution may require a swap context, who takes care of previous version instances while updating.
Keeping a time scheduled task to check new plugins and new versions, and then block plugin module usage, swap files, reload, and unblock, reinstancing new versions from previous if necessary.

Dynamically update dlls on running instance

We have a service running that connects with hundreds of devices over TCP. Every time we want to do an update of this service we need to restart it and this causes a connection loss for all devices.
To prevent this we want to divide our application into a connection part and a business logic/datalayer part. This will give us the option to update the business logic/datalayer without restarting the connection part. This could be done with WCF services, but the system should response as fast a possible and introducing another connection to something will cause an extra delay.
Would it be possible to update a dll file without restarting the application and give the application an instruction so it will load the new dll and discharge the old one? Off course as long as the interface between the layers don't break.
According to MSDN:
"There is no way to unload an individual assembly without unloading all of the application domains that contain it. Even if the assembly goes out of scope, the actual assembly file will remain loaded until all application domains that contain it are unloaded."
Reference: http://msdn.microsoft.com/en-us/library/ms173101(v=vs.90).aspx
My approach would probably involve some sort of local communication between communication layer and business logic, each on a different context (AppDomain) - via named pipes or memory mapped files, for example.
Here is a good example of loading / unloading assembly dynamically.
http://www.c-sharpcorner.com/uploadfile/girish.nehte/how-to-unload-an-assembly-loaded-dynamically-using-reflection/
Be careful about speed since the MethodInfo.Invoke is slow you might want to look into using DynamicMethod. Also creating / destroying app domains is slow.
http://www.wintellect.com/blogs/krome/getting-to-know-dynamicmethod
Also you can use what is called a "plugin" framework. Codeplex has one called the MEF "Managed Extensibility Framework"
http://mef.codeplex.com/

Prohibit starting a form in third-part dll plugin (c# service)

I have the a service, that loads some dlls and starts a function in each dll. Each dll contains some rules, that can be also developed by our clients (something like plugin system). The problem is, that clients can theoretically add forms to be called inside dlls. So the goal is to disallow that, or, at least block such dlls.
The only method I can imagine now is call each dll in a separate thread and kill it after some timeout.
But I think it is not so nice.
Please advice me a better method. Thankx.
The best way to deal with plug-ins is to "sandbox" each one of them in an individual app domain. This way you can safely react to their execution errors, unload them if you need to, and manage them in whatever ways you like. But most importantly for this question, you can monitor their loading of assemblies using this event hook. If you see them loading a DLL that you do not want to allow, you can simply throw an exception. Your code would catch the exception, clean up the app domain, and optionally send the clients a warning for trying to do something that is not allowed.
The only downside to this approach is that it is rather non-trivial to implement.
It is VERY hard problem to protect server from third party code that you need to execute.
I would recommend reading on SharePoint sandbox approach (i.e. http://msdn.microsoft.com/en-us/library/ff798382.aspx) which tries to solve this and related issues.
As SLaks said - you implicitly trust code by simply executing it. Unless you expect code to be outright evil you may be better of by simply logging how long calls take (and maybe time out if possible) and provide your client with this information. Since it seems like client creates the code for themselves it is unlikely that code will be explicitly made non-functional.
Other interesting issues outside showing a Form:
stack overflow exception (easy to create, hard to handle)
while(true); code that never returns control
access to native code if full trust enabled.
You could always use reflection to inspect their code and ensure that certain namespaces and classes (e.g. System.Windows.Forms.*) are not referenced or used.
SQLCLR restricts what is allowed to be used/referenced in assemblies installed as SQLCLR extensions, and that appears to be done that way: http://msdn.microsoft.com/en-us/library/ms403273.aspx

Prohobit type usage across default or not AppDomain

Is it possible to somehow prevent a type usage across an AppDomain (preferably in default)?
Clarification: I want to an exception (preferably compiler error) occurs on some type usage / instantiation / member access. I want to prohobit a direct usage of EventLog in favour of TraceSource.
You can't get compile time error for classes loaded into an AppDomain since AppDomains are runtime concept. I don't know about run-tim way.
I would not recommned even trying to block usage of system classes like EventLog - you never know what other libraries use.
As an option you can do compile time check of your code to prohibit function calls (i.e. by using custom FXCop rule). You can also do similar check at run time for assemblies you are loading, also you will need to write more infrastructure to do so.

How to share a process?

How can I snuggle into another process? Like, share another process's name? So if my application is griddemo.exe, and I want to snug into, let's say, explorer.exe, is that possible? Just read something about CreateRemoteThread() from kernel32. Is that in the right direction? Would there be security/UAC issues?
First of all sorry, but my answer will be longer as another answers.
I use DLL injection since years in different version of operation system (from windows NT 4.0 till Windows 7) and I had no time any problem with any virus scanner (inclusive both Norton and McAfee in different versions). So I disagree with Stephen Cleary (see his answer) in this aspect.
Usage of CreateRemoteThread() is really only one of the ways. AppInit_DLLs is another way. Both has its advantage and disadvantage. The main advantage of AppInit_DLLs is a simplicity to inject DLL in any process. The main disadvantages of AppInit_DLLs approach are following:
All GUI application will load the DLL. If you want to load it only in one process like explorer.exe you can't do this. So the working space of all GUI processes will be increased by your DLL. An error in your DLL (especially inside of DllMain or in any dependency DLL of your DLL) can crash many processes which you don't currently know.
You can not inject your DLL with respect of AppInit_DLLs approach in a console application or in any EXE which have no dependency to User32.dll.
You should be very careful inside of your DllMain, because it will be called before User32.dll will be full initialized. So a safe DLL which you can use inside of DllMain of your DLL is Kernel32.dll.
With respect of CreateRemoteThread() one can start an additional thread in a process. The main problem of CreateRemoteThread() is that its lpStartAddress parameter must be an address from the remote process. So one have to use functions OpenProcess, VirtualAllocEx and WriteProcessMemory to write some information into the memory of the destination process. To be able to open a process one have to have debug privilege enabled. If you want to do only 2 + 2 inside of the destination process you can copy the corresponding binary code directly into destination process. All real interesting work can be done with usage of some Windows API. So mostly one don't copy a code. Instead of that one call LoadLibrary("MyPath\\MyDll.dll") inside of destination process. Because the prototype of LoadLibrary is the same as prototype of ThreadProc of CreateThread you can call LoadLibrary as a ThreadProc of CreateRemoteThread(). This way has the name DLL Injection.
I recommend you to use this DLL Injection only if it really required. If your destination application has some other way like plug-ins to load you DLL inside the process your should use this way instead of DLL Injection.
Some general problems you will have to solve after you have a working example of DLL Injection. This problems you can don't see at the first time, but after a long usage of your application you will see its importance:
You should find the moment when the destination process are already running before you can use CreateRemoteThread().
The destination application must be already initialized before you call CreateRemoteThread(). So you should not use CreateRemoteThread() too early. In case of explorer.exe you can use a start of your small trigger program from Run registry key. At the moment is explorer.exe fully prepared for DLL injection.
You should take in consideration 64-bit version of Windows.
Don't forget about DLL relocation inside of destination process. Be careful, that you DLL can be loaded in the destination process at the other address as in your process. Mostly it is a good idea to choose a good base address (linker option) for you DLL which you will inject. The Kernel32.dll can be sometime (very seldom) loaded at the other address as in your source process. You can create a DLL Injection code which are free of this problem.
Terminal Services isolates each terminal session by design. Therefore, CreateRemoteThread fails if the target process is in a different session than the calling process. The problem you can see on XP (which is not connected to domain) or especially on Vista or Windows 7 if you try make DLL injection from a windows service. To fix the problem you should make DLL Injection either from the process running on the same terminal session as destination process or you have to switch current session before using of CreateRemoteThread. Your process must have SE_TCB_NAME privilege enabled and use SetTokenInformation with TokenSessionId parameter. To get session id of the destination process you can use different methods. Functions with the prefix WTS (like WTSGetActiveConsoleSessionId) can be very useful.
So everything is not very easy, but it is really interesting subject where you can study a lot of things about operating system. You should only spend a little time to analyse your problem and different ways to solve it before you choose one way which corresponds your project requirements and start programming.
DLL injection is the traditional method of doing this. It's quite tricky, especially since virus scanners look askance at the practice. So even if you get it working, Norton/McAfee would be likely to block you - or block you in the future.
One easy way of DLL injection is the AppInit_DLLs registry value. Note that Microsoft has reserved the right to simply remove this functionality (and likely will do so in the future).
The Microsoft-approved way to achieve DLL injection is licensing Microsoft Detours.
Note that your DLL must be built against the CLR version 4.0 or higher to perform DLL injection safely, because this is the first version to support in-proc side-by-side.
If you mean injecting your code into another process, then dll injection is one technique:
http://en.wikipedia.org/wiki/DLL_injection
Haven't done this for years, so not sure how happy modern MS Windows operating systems (i.e. post XP) are going to be with this.
I've not tried this lately, but another way to do this would be to create a Hook DLL:
Create a DLL that contains a Hook Procedure like MessageProc.
Install this DLL into Windows\System32.
Use FindWindows(Ex) to locate your victim process' window.
Use GetWindowThreadProcessId() to find the owning thread of that window. This is necessary to avoid injecting your DLL into every single process on the system.
Use SetWindowsHookEx to hook that thread.
PostMessage a WM_USER message to the window - activating your Hook DLL if it isn't already active.
This would likely invoke the new Windows Vista/7 UIPI/UAC if you're not a sufficiently privileged user but this depends on many factors - your mileage may vary.

Categories

Resources