Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plugin system security in .NET Framework 4.x (without CAS)

What I'd like to achieve is a plugin system with the following features:

  • loading external plugins, from sources potentially not trusted by me (the developer), but trusted by the end-user who installed the plugin
  • granting per-plugin permissions within a specific scope; e.g. one plugin may have a permission to read files from a specific location, while others may be allowed to connect to specific website location
  • a special case of per-plugin permissions: interacts with another object, most likely provided as an interface instance, without accessing any of its non-public members (not even with sneaky Reflection techniques)
  • prevention of actions the end-user didn't agree to, such as accessing non-public members or operating on the filesystem, before the plugin code can do any harm

During my search, I've mostly found SO solutions involving Code Access Security which, as far as I know, is outdated as of .NET 4.x. I've also read up a bit on the new security model on MSDN pages, and it seems library code that exposes protected resources will be necessary here; however, I could not find any examples showing how to apply such code. My guess is that it'll involve creating separate AppDomains and possibly playing around with Principal permissions, but that's about as far as my knowledge gets.

On a side note, I've also found mentions of requiring strongly named assemblies only, but I'm not convinced that'll be enough. If I'm not mistaken, one of the strong naming benefits is that the plugin developer can prove their own identity by signing the assembly hash with own private key, and others can check by using well-known and trusted public key. However, this alone seems too inflexible, as it either requires the developer to personally decide whose code should be trusted or just trust anyone who learned to sign their assembly.

I'll be very grateful for a good example of security management code using the most up-to-date security model. What I currently have in mind:

  • an interface for service exposing potentially sensitive operations (say, A and B)
  • a dummy implementation of the service, focusing on preventing the unauthorised execution of these operations
  • two plugins from separate assemblies, one with permission to perform operation A and other with permission for operation B
  • an application that sets up the service, loads the assemblies with plugins and tries to perform operations for each of these, so that unauthorised operations are blocked and authorised operations are executed correctly
  • when run within the application, neither plugin on its own should be able to access general sensitive APIs, such as file I/O or networking, but it should be possible to do through the service
  • all that while following these recommendations as closely as feasible (as opposed to CAS-based solutions from SO questions back from year 2010)

Of course, you are welcome to suggest an alternative architecture, if it achieves the goal in a better way.

like image 234
Alice Avatar asked Mar 25 '18 18:03

Alice


2 Answers

What you are asking is hard on multiple levels.

Closest thing I've seen to this is a long forgotten Microsoft project called Terrarium, where you code a creature using a .net language, build it, and submit your assembly containing your creature to live on a terrarium server which was written in .NET 1.0. It was a challenge for MS developers to create an environment where any user can run code but be secure and play nice. They created a tool to ban certain types to be used in assembly. It is called AsmCheck.

I had tried to achieve same thing using app domains in past without much success.

From time to time I still think about what is the best way to achieve such task. It is possible, Android and iOS works like that, but it requires me to write entire OS or framework as best.

I've planned to create an AppDomain and load my plugin loader to this domain. Loader then loads the plugin assembly and all the assemblies it tries to load by hijacking assembly loader. When loading an assembly it uses AsmCheck.vNext to check if it does something shady. For every assembly it loaded, it uses an IoC container (like this) to limit access to framework.

Verification of assemblies is done on my side by checking strong names with my plugin registry, or checking certificates for code signing.

All seems good until you see Confuser or its successor ConfuserEx. It creates proxy types to access methods by converting method to self initializing static delegates that references methods not by name but a reference id. Now, how can I possibly analyse and/or limit access to this.

Or you can prevent System.IO namespace altogether and provide you own IO library, but how can you limit one to use PInvoke and call GetProcAddress so it can access ReadFile, WriteFile, etc...

Just way too many cases to handle, and this is only the tip of the iceberg. If you absolutely have to limit plugins to do stuff you have to write you own framework or provide a scripting language like lua.

You can try App Containerization. Every plugin is loaded in a special container and talks to your app to perform tasks that require permissions. Other than that, code running in container think container is the whole computer.

One day I'd like to see someone solve this problem in a simple and efficient way.

PS: My answer is not an answer. It is an answer because it just does not fit in a comment.

like image 162
Erdogan Kurtur Avatar answered Nov 04 '22 02:11

Erdogan Kurtur


You can force plugins to run in separate process and interact with your application only using RPC. This way they won´t have access on anything except you provided through API.

Android operating system does same thing to expose functionality for Applications Look IBinder.

enter image description here

like image 34
Davit Tvildiani Avatar answered Nov 04 '22 03:11

Davit Tvildiani