javax.script 的一个大问题包裹JSR-223是缺少任何明显的方法来沙盒运行的脚本。所以显而易见的问题是:如何对 JSR-223 脚本进行沙盒处理?有人问过这个问题,甚至有人尝试回答这个问题。
这里有两个有趣的问题问这个问题但不幸的是没有捕获要点:
要点在于,这不仅仅是设置正确的安全策略或使用正确的 ClassLoader 的问题,因为您要保护的代码不是 Java 代码,而且它没有类。您可以尝试通过使用 ClassLoader 为其提供特殊的 ProtectionDomain 来保护 ScriptEngine,但这仅在系统 ClassLoader 无法找到 ScriptEngine 以通过使用错误的 ProtectionDomain 加载类来打败您的努力时才有效,该 ProtectionDomain 是绑定(bind)的发生在作为 JRE 的一部分有用地包含的任何 ScriptEngine 上。
这是另一个看起来不错但没有捕获要点的资源:Simple JVM sandboxing .它告诉粗心的人,他们可以通过在自定义 AccessControlContext 中使用 doPrivileged
来沙盒他们的脚本,该 AccessControlContext 包含一个 ProtectionDomain,但当然这样做是没有意义的,因为 doPrivileged
是仅对获得权限有用,对拒绝权限没有用。如果不受信任的代码已经在沙箱 ProtectionDomain 中,那么 doPrivileged
技巧根本不会做任何事情,如果不受信任的代码在非沙箱 ProtectionDomain 中,那么它可以调用 doPrivileged
并完全绕过沙盒尝试。
真正的问题是如何解决这些问题?假设我们打算使用 ProtectionDomains,似乎唯一的选择是给 ScriptEngineManager 一个自定义的 ClassLoader,它故意从系统 ClassLoader 中隐藏一些类。那么,我们如何决定将哪些类放入沙箱,哪些从系统ClassLoader中获取呢?似乎没有任何可靠的方法可以知道哪些类可能负责为脚本提供脱离沙箱的方法,尤其是对于尚不存在的 ScriptEngine。
我能想到的唯一选择是我真正想问的问题。简单地忽略 ProtectionDomains 并实现一个具有用于评估脚本的沙箱模式的自定义 SecurityManager 是否是更好的解决方案?例如:
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--; }
}
}
这看起来既棘手又危险。当涉及到安全问题时试图狡猾是很危险的,但在这种情况下这真的是最好的解决方案吗?
最佳答案
两个参数 doPrivileged
可用于减少权限。为该方法提供一个 acc,其中仅包含您要授予的权限。
如果您使用缩减的权限集启动脚本引擎,权限检查将看到缩减的权限集。 AccessController.doPrivileged
和 Method.invoke
之类的东西都得到了处理。当然,这需要正确实现特定的脚本引擎实现。可以通过通常的方式报告 JDK 实现中的错误。
您仍然在运行不受信任的代码。即使是字节码,在 Java 中也很难防范。
关于java - 是否应该使用自定义 SecurityManager 来对 javax.script.ScriptEngine 进行沙盒处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19973646/