Does CS-Script provide sandboxing out of box? - c#

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

Related

Roslyn c# scripting sandbox

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.

Best way to only perform a function if a (.NET) DLL is loaded?

I am not sure the best way to explain this so please leave comments if you do not understand.
Basically, I have a few libraries for various tasks to work with different programs - notification is just one example.
Now, I am building a new program, and I want it to be as lightweight as possible. Whilst I would like to include my notification engine, I do not think many people would actually use its functionality, so, I would rather not include it by default - just as an optional download.
How would I program this?
With unmanaged Dlls and P/Invoke, I can basically wrap the whole lot in a try/catch loop, but I am not sure about the managed version.
So far, the best way I can think of is to check if the DLL file exists upon startup then set a field bool or similar, and every time I would like a notification to be fired, I could do an if/check the bool and fire...
I have seen from the debug window that DLL files are only loaded as they are needed. The program would obviously compile as all components will be visible to the project, but would it run on the end users machine without the DLL?
More importantly, is there a better way of doing this?
I would ideally like to have nothing about notifications in my application and somehow have it so that if the DLL file is downloaded, it adds this functionality externally. It really is not the end of the world to have a few extra bytes calling notification("blabla"); (or similar), but I am thinking a lot further down the line when I have much bigger intentions and just want to know best practices for this sort of thing.
I do not think many people would
actually use its functionality, so, I
would rather not include it by default
- just as an optional download.
Such things are typically described as plugins (or add-ons, or extensions).
Since .NET 4, the standard way to do that is with the Managed Exensibility Framework. It is included in the framework as the System.ComponentModel.Composition assembly and namespace. To get started, it is best to read the MSDN article and the MEF programming guide.
You can use System.Reflection.Assembly and its LoadFile method to dynamically load a DLL. You can then use the methods in Assembly to get Classes, types etc. embedded in the DLL and call them.
If you just check if the .dll exists or load every .dll in a plugin directory you can get what you want.
To your question if the program will run on the user's machine without the dlls already being present - yes , the program would run. As long as you dont do something that needs the runtime to load the classes defined in the dll , it does not matter if the dll is missing from the machine. To the aspect you are looking for regarding loading the dll on demand , I think you are well of using some sort of a configuration and Reflection ( either directly or by some IoC strategy. )
Try to load the plugin at startup.
Instead of checking a boolean all over the place, you can create a delegate field for the notification and initialize it to a no-op function. If loading the plugin succeeds, assign the delegate to the plugin implementation. Then everywhere the event occurs can just call the delegate, without worrying about the fact that the plugin might or might not be available.

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.

(C#/C++ CLI) Is it possible to protect my C++ CLI assemblies from being used in other .NET projects?

I have created a C++ CLI wrapper for native C++ code, which in turn I reference in my C# application. Is it possible to somehow protect this assembly so that it may only be used in my application without the possibility of someone else using it?
I'm a Microsoft technology developer, I'm all about selfishness :)
I have used this technique with success.
Basically, it's about protecting your assembly from being loaded by placing a link-time security demand and using the assembly strong name's public key as evidence. Only assemblies signed with your private key will be able to load it.
Yes, but this will be a losing battle against a determined attacker.
For example, you could provide an encrypted version that only accepts a particular key, as some people have suggested. But then you'll need to decrypt it on your clients, who may not have encrypted memory stores, so a determined attacker could simply read the appropriate block of memory and deserialize the result to get your original assembly.
Not perfectly. LinkDemand is only enforced in a partial trust environment. Code running with full trust can also use reflection to access private types, and generally bypass any protection you care to discuss.
Maybe you want your C++/CLI code to call Assembly::GetEntryAssembly and check it against a whitelist of approved apps for which the library is intended.
Of course, you want to minimize the amount of managed code (and attributes) involved in the checks since managed code is really easy to decompile.
Actually, mixing the occasional check into the core logic of the C++ code is the only hope you have that it won't be bypassed.

Serialization Assembly. Is it needed or not?

I have a .net 2.0 c# ClickOnce app and it connects to its data via Web Services. I've been told that one way to potentially speed up the application is to generate a serialization assembly beforehand. I have several questions on this front.
The default setting to whether to generate a serialization assembly is Auto. What criteria does VS2005 use to decide whether to generate a serialization assembly or not? It seems like it does not generate under Debug configuration, but it does under Release configuration, but I can't tell for sure and can't the information anywhere.
Does serialization assembly actually improve the startup of the application? Specifically what does it improve? Do I actually need a serialization assembly?
It is really asking "Shall I pre-generate the serialization assemblies and include it in the deployed project or shall I fall back on the default of generating the assemblies on the fly?" Generally that won't hurt too much after the first hit perf-wise. Where it can play in is that the serialization assemblies are generated in %SYSTEMROOT%\TEMP. Which, in some cases, the process can't access, leading to fatal exceptions in most cases.
This is not relevant to your situation, but there's another good reason for pre-generating the serialization assembly - it's necessary when hosting your code in SQL Server (i.e. SQLCLR). SQL Server doesn't allow these assemblies to be generated dynamically, so your serialization code would fail inside SQL Server.
In most cases, you aren't likely to see a huge benefit from this, especially if you keep the app open for a while. Pre-generating a serialization assembly mainly helps the first time (in an exe lifetime) that you serialize a specific type as xml.
According to Intellitrace, only the first time you XML-serialize a type, a FileNotFoundException is thrown and then caught. This means CLR expects to load an assembly containing all the XML-Serializers for that specific Assembly and when it's not found, a FileNotFoundException is thrown to signal the XmlSerializer: "Hey! Generate the darn assembly!" and this is what happens during that "Catch" and then the previously not found file exists.
I've read somewhere that using try-catch for logic is a bad exercise. IDK why Microsoft has used this approach...

Categories