Should I use a special SecurityManager for the javax.script.ScriptEngine sandbox?

The big problem with the javax.script JSR-223 package is the lack of any obvious way for the sandboxed script to run. So the obvious question is: how do you use JSR-223 scripts for the sandbox? This was asked, and there were even several attempts at answers.

Here are two interesting questions that ask this problem, but unfortunately there is not enough point:

The point is that this is not just setting the right security policy or using the right ClassLoader, because the code you are trying to protect is not Java code and it does not have a class. You can try to protect ScriptEngine with ClassLoader to provide it with a special ProtectionDomain, but this only works until the ClassLoader system can find ScriptEngine to defeat your efforts by loading the class with the wrong ProtectionDomain that is associated with any ScriptEngine that will ever be included as part of the jre.

Here is another resource that looks nice but doesn't fit: A simple JVM sandbox . This suggests that they can isolate their scripts with doPrivileged in a custom AccessControlContext that contains ProtectionDomain with very few permissions, but of course this is pointless because doPrivileged is only useful for getting permissions and not useful for refusing permission. If the untrusted code is already in the ProtectionDomain doPrivileged trick doPrivileged do nothing at all, and if the untrusted code is in the non-sandbox ProtectionDomain, then it can just call doPrivileged and completely bypass the sandbox attempt.

The real question is: how can I get around these problems? Assuming we intend to use ProtectionDomains, it seems that the only option is to give ScriptEngineManager its own custom ClassLoader class, which deliberately obscures some classes from the ClassLoader system. In this case, how do we decide which classes to put in the sandbox and which can be obtained from the ClassLoader system? There seems to be no reliable way to find out which classes can be responsible for providing the script with a means of exiting the sandbox, especially for ScriptEngines that don't exist yet.

The only alternative I can think of is what I really want to ask. Would it be a better solution to just ignore ProtectionDomains and implement your own SecurityManager, which has sandbox mode for evaluating scripts? For instance:

 public final class SandboxMan extends SecurityManager { private int sandboxDepth = 0; @Override public void checkPermission(Permission permission) { if(sandboxDepth > 0) throw new SecurityException("Sandboxed: " + permission); else super.checkPermission(permission); } @Override public void checkPermission(Permission permission, Object context) { if(sandboxDepth > 0) throw new SecurityException("Sandboxed: " + permission); else super.checkPermission(permission, context); } public Object eval(ScriptEngine engine, String script) throws ScriptException { if(sandboxDepth == Integer.MAX_VALUE) throw new SecurityException("Sandbox depth"); sandboxDepth++; try { return engine.eval(script); } finally { sandboxDepth--; } } } 

It looks complicated and dangerous. It is dangerous to try to be difficult when it comes to security, but could this be the best solution given the situation?

+6
source share
1 answer

Two doPrivileged arguments can be used to reduce privileges. Deliver the method with acc only with the permissions you want to give.

If you run the script engine with a reduced permission set, permission checks will see the reduced set. The same AccessController.doPrivileged and Method.invoke . This, of course, requires the correct implementation of a specific script engine implementation. Errors in the JDK implementation can be reported in the usual way.

You are still left with untrusted code. Even as bytecode, it can be difficult to protect in Java.

0
source

Source: https://habr.com/ru/post/958055/


All Articles