Animesh Sahu
Animesh Sahu

Reputation: 8096

How to build a safe (restricted ecosystem) plugin based architecture (in Kotlin)

So primarily I try the simple architecture in which I make a common interface's repo and then pull it on every plugin and then implement that, then call the main app for adding the plugin and run it dynamically while running.

interface PluginI {
    val core: CoreApplication   // Means of communication with core app, this obj is sent by core app by constructor

    fun version(): Double
    suspend fun load(pluginConfiguration: PluginConfiguration)
    suspend fun run()
}

But how should the plugin be restricted to some area, such as protection from potentially destroying, hijacking or crashing the main app? Especially it should be restricted from using anything from jvm's static classes such as System, an example of some hijacking app is that it could do a System.getRuntime().exec() which could be execute exploits in shell.

Sandboxing isn't the solution, or is it? Because it just breaks the connection between the main app and plugin.

I am searching for a solution which gives only a shared object from which main app communicates with plugin and send some info it wants such as date/time or whatever that can't hurt runtime.

Upvotes: 3

Views: 833

Answers (1)

GotoFinal
GotoFinal

Reputation: 3675

Creating sandboxed environment in java is pretty much impossible, with java 9+ you could use modules to make this a bit easier... especially if you want to allow some kind of reflections.

But allowing reflections otherwise is really hard and risky, and everything you do should definitely work as a whitelist, blacklists just "don't work" (aka, I don't believe anyone will be able to find all the things to include and remember to keep it updated when updating any of your dependencies).

Java have a build-in system for such stuff and its called SecurityManager, your application should setup own SecurityManager and use it to filter every method call and only allow for invocation of method from the same plugin as it was called from and block any kind of reflections, block changing security manager and block any manual class loading.

Additionally java 9 modules can be used to simplify this setup, as modules can even block calls between modules while not restricting reflections on classes from the same module. But it can't replace security manager fully.

Also just remember that no matter what you do, someone can still cause your application to become unstable, especially if you will allow any kind of I/O or own threading. But plugin can still allocate huge amount of memory or just run infinite loop - or actually just both at the same time ;) And there is no way in java to either force thread to be stopped or limit amount of allocated memory from some code.
The only partial solution for this I could see would be to use java agent to instrument code of each plugin and add calls checking if thread was interrupted inside any code that could run for too long.
Same would be possible with allocations.
But then you also need to be 100% sure that none of the whitelisted methods can loop or allocate too much at once.

Basically: don't.

It's only good solution (without the agent) if you can trust plugin a bit but you just want to set some rules to avoid bad practices. It will not stop someone who wants to break something, but will stop typical programmer from creating non-clean code.

If you need to run untrusted code... either run it in actual sandbox on OS level, like look at sphere engine and only communicate with it in some safe way.
Or use some other language that offers you to do the same as stated above but much easier, like Lua. http://lua-users.org/wiki/SandBoxes You can then run such language from java using script engine https://github.com/luaj/luaj But even then its hard to be 100% sure it will work right and that there are no holes someone will find and use, as it does not take much if all that an attacker will need is to stress cpu/memory enough to disrupt main application.

Upvotes: 3

Related Questions