Roslyn c# scripting sandbox - c#

Is there a way to sandbox execution of a script such that it a) Can't do anything "dangerous" and b) it can access any files it wants to so long as the file is within the same directory as the script file itself. Kind-of as-if it were to treat all file-paths as relative.
I guess I'm asking about Roslyn's scripting security measures and their level of customization.

This is possible, but as SLaks says, it is a hard problem. You should probably read In .NET 4.0, how do I 'sandbox' an in-memory assembly and execute a method?. You would need the following steps
Use a CSharpCodeProvider or VBCodeProvider to compile the source to an assembly on the harddrive.
Create a new AppDomain granting it only those permissions you would like it to have.
Use MarshalByRefObject's to communicate back and forth between your original AppDomain and the child AppDomain you've just created. See this and this.

Related

Does CS-Script provide sandboxing out of box?

I'm researching cs-script and I'm wondering about how secure it is, out of the box. I know a script is loaded and unloaded dynamically, but can that script escape its executing assembly? i.e. can it use reflection to access and instantiate classes from other assemblies in the same process?
So my question is does cs-script come with built-in security by default or does it not bother?
If you mean CS-Script as per http://www.csscript.net/, then yes it can reference and call into other assemblies, with the normal syntax:
using MyOtherAssembly;
CS-Script uses implicit loading to try and work out which assembly to load based on the namespace in the using statement. This is not guaranteed to work in all circumstances, in which case you will need to use explicit loading, e.g., you can give CS-Script a directive to explicitly load the required assembly:
//css_ref "..\MyOtherAssembly.dll"
using MyOtherAssembly;
The //css_ref is a special comment that is processed by CS-Script as a directive to load the assembly, in this case the referenced assembly is in the parent directory of the script. This does a similar job as an assembly reference in a project file for a normal assembly. You can also use the CS-Script command line to explicitly load assemblies.
I have also found that you do not need to use either implicit or explicit loading if the referenced assembly has already been loaded into the AppDomain before the script is called. I assume CS-Script detects that the namespace already exists in the AppDomain, so does not bother with the implicit loading.
More information about the assembly loading is given here: http://www.csscript.net/help/using_.net_assemblies.html.
Edit1: You can't disable the implicit loading, but you could put the script into a directory without any other assemblies, which will prevent the implicit loading from being able to find any other assemblies. The script will still be able to call into namespaces that are already loaded. But this is only "security by obscurity"; the very nature of managed code means that it is always possible for a determined person to access your code via reflection.
In short: No, CS-script does not provide any security features out of box.
Answered here: https://stackoverflow.com/a/8692459/1657476
The immediate attractive solution is to use .NET Sandbox. It is
designed exactly for this sort of scenarios.The CLR standard
sandboxing is available for the host application running scripts with
CS-Script. The idea is that you initialise CAS before loading the
suspicious script and the rest is a CLR responsibility. And if you
need to configure directories/files permissions you do it with CAS
tools. This way scripting is a "transportation" for the routine
provided by your user. And CS-Script is a convenient mechanism for
implementing such transport but the actual security concerns are
addressed by .NET Sendoxing, which has comprehensive set of
functionality to cover practically all possible security scenarios.
With CS-script downloadables you can find the Sendboxing sample
(\Samples\Sandboxing) which demonstrates how to prevent script from
file I/O operations (e.g. create file).
A sample of using .Net Security Credentials with cs-script is available at: http://www.csscript.net/Samples.html (sandbox.zip)
To make execute an untrusted cs-script securely (as isolated as possible), create a new AppDomain with Security restrictions, before loading a script (into the new app domain). Data can then be marshaled between the primary- and script-domains.
See https://msdn.microsoft.com/en-us/library/bb763046%28v=vs.110%29.aspx

C# DLL from VBScript, no regasm

Is it possible to access a C# DLL's method from VBScript without registering it with regasm? I will be creating the DLL so pretty much any exotic requirement to make it visible to VBScript, I can do...
I have read here that it might be possible to use GetObject from VBScript to achieve this, but I have tried that with no success... Is there anything else I need to do aside from making the DLL "COM visible" to make this work?
The reason why I need to avoid regasm is that it requires admin rights, and I need to deploy this DLL "silently" to many clients that may or may not have admin rights.
No, registration is required, the only way that the script interpreter can find the DLL that contains the ProgId that you use in the script's CreateObject() call. Isolated COM with a manifest doesn't work, you can't modify the manifest for the script interpreter.
There is a technical solution, you can write registry keys in the HKCU registry hive without acquiring UAC elevation. The Regasm.exe tool always writes them in the HKLM hive. That registers the assembly as well, but only for the user that runs Regasm.exe. It is however pretty painful and easy to get wrong, you have to write your own registration method and apply the [ComRegisterFunction] attribute. It is now your job to use the RegistryKey class to set the keys. Same for the [ComUnregisterFunction], it should delete the keys again. There are a lot of bad examples out on the interwebs, best way to get this right is to use SysInternals' ProcMon to observe the registry keys that get written when you use Regasm.exe normally, then reproduce that in your own code, using HKCU instead.
Do note the other side of that medal, you are in fact making configuration changes to the machine that allows arbitrary code to run. Trying to hide that doesn't do the user any favors and should never be considered if you honor the user's desire to keep the machine safe and predictable. UAC is not there to stop you from making changes, it is only there to inform the user about it.
The accepted answer is incorrect that registration is required to use a DLL. You can use the GetObject() method instead of the CreateObject() method as shown in my answer to this question.
Using DLLs in VBScript

Accessing resources in registered .NET DLL via res protocol

I have a .NET DLL that I register with regasm.exe as a Browser Helper Object. I embedded several Win32 resources in the DLL using .res files and /win32 switch to csc.exe.
image.png HTML "image.png"
I am able to access the resources using the res protocol as long as I include the absolute path of the DLL.
res://C:\Path\To\My\Dll\Assembly.dll/image.png
This is rather unfortunate. I would much rather just reference the assembly name as I have seen in many other examples:
res://Assembly.dll/image.png
But this results in an error because the browser can't find the resource.
Ideas?
I think there are a couple things that can be done. First, I believe your assembly needs to be a part of the global assembly cache if you don't want to be forced to use the full path.
Add assembly to global assembly cache.
It's not pretty and you must also keep in mind that a newer build of the DLL will be different from the version in cache. So it would essentially be another extra step to take which would just lead us back to accepting having to put in the full path in the first place.
Second, another solution I believe that works would be to place the DLL in the same directory as the VS utility or the other resources you're trying to use. This could be applicable to multiple different things that one might want to do, but requires manually moving your files around.
Third, you create some custom environmental variables that represent the path that you desire. So instead of typing the full path in the future, you just type your variable.
The third option is my favorite and something that I use for multiple different things I need to accomplish from the command-line.

How to prevent access to local file system

I have a situation in which my (C#) application can load external DLLs (not written by me) and execute code from those libraries. The libraries can be C# or CPP.
I need to make sure this external code won't access any files in my local file system (read and write) except from a specific folder.
How can i do that?
I've seen third-party code that does this; for example, Jint lets you write JavaScript scripts that manipulate CLR objects, but it prevents any JavaScript-originated code paths from accessing the filesystem, Reflection, etc. by using permissions.
You can read Jint's documentation and poke through their source code for more details, but the essence of it seems to be this:
PermissionSet myPermissionSet = new PermissionSet(PermissionState.None);
// or some other permission set, depending on your requirements
try {
myPermissionSet.PermitOnly();
// run untrusted code
} finally {
CodeAccessSecurity.RevertPermitOnly();
}
A lot of things I've read say you need to create a sandboxed Appdomain (something I've never had much success with), but Jint's approach seems to work pretty well. You might have to watch out for the third-party code hooking static events that would fire later, though -- then they could escape the PermitOnly scope.
Run the application as a restricted user account and only grant the user access to that specific folder.
Secure the files through the OS facilities (filesystem privs), create an account that can access only those files and use this account to run the application
It depends on your framework, but you can use Caspol (Code Access Security Policy) up to .Net 3.5 (and I think C++ DLLs also) to specify security privileges including IO access.
Hope that helps :)
Take a look at Molebox, maybe it will fit your needs. Molebox lets you wrap modules to sandbox them.

ASP.NET websites referencing common, updatable Assembly

I'm developing a component (HttpModule) that's used by a number of web applications on a .NET website, and I want the component to be easily maintainable. I've come up with something outlined below but wanted to see if there were any positive/negative thoughts or general feedback on the implementation, as I'm not 100% familiar with Assembly loading, especially in terms of memory overhead.
(I don't really want to do this: Create Your Own .NET Assembly Cache)
The lightweight HttpModule itself is in the GAC and referenced from the site's root web.config. On each request it opens a text file (stored in the web's root/bin) that contains just a strong named's assembly name (e.g. "My.MyLibrary, Version=1.1.0.0, Culture=en, PublicKeyToken=03689116d3a4ae33") and then checks the current AppDomain to see if it is already referenced (iterates over GetAssemblies()). If not, it then calls Assembly.Load to load myLibrary and uses basic Reflection to Invoke() a custom method in My.MyLibrary that actually does the intended processing work of the HttpModule.
My.MyLibrary itself is also in the GAC. To upgrade the app without any app restarts, put a new version in the GAC, and just edit the string in the text file. I'm using the text file because a) it's fast and b) I didn't want to have to update a machine/web.config and cause a recycle to redirect the HttpModule to use a new version of My.MyLibrary. It seems to work okay. The old version can be uninstalled from the GAC when it's finally ready to be. So hopefully the only time an app pool/iis reset would be needed would be to change the HttpModule part.
Any replies much appreciated!
-Will
Personally I would say if you can avoid using any late binding it would be better, but as you want to be able to have the freedom to just throw a new assembly at your application then it does seem like late binding makes sense.
With regards to your method of storing and retrieving the list of assemblies, I would use an XML object and load it from the file. You will find adding extra information to it simpler this way, otherwise you will have to maintain your own file format.
You may also want to consider adding some code to catch errors generated from these assemblies, unload them and put a flag in your file telling your HttpModule not to load it until it has been updated.

Categories