我正在尝试向我们的系统添加脚本功能,其中不受信任的用户可以编写简单的脚本并让它们在服务器端执行。我正在尝试使用Nashorn作为脚本引擎。
不幸的是,他们为Nashorn添加了一些非标准功能:
https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/shell.html#sthref29
向下滚动到“Additional Nashorn Built-in Functions”并查看“quit()”函数。是的,如果不信任的用户运行此代码,则整个JVM都会关闭。
这很奇怪,因为Nashorn特别期望运行不受信任的脚本。请参阅:https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/api.html#classfilter_introduction
嵌入Nashorn的应用程序,特别是服务器端JavaScript 框架,通常必须从不受信任的来源运行脚本 因此必须限制对Java API的访问。这些应用可以 实现ClassFilter接口以限制Java类访问 Java类的子集。
有没有办法阻止这种行为?如何阻止用户运行任何其他功能?
答案 0 :(得分:7)
不幸的是,目前无法控制非标准全局函数的创建。一种解决方法是在ScriptEngine初始化后从全局对象中删除这些函数:
final NashornScriptEngineFactory engineManager = new NashornScriptEngineFactory();
final ScriptEngine engine = engineManager.getScriptEngine();
final Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
bindings.remove("print");
bindings.remove("load");
bindings.remove("loadWithNewGlobal");
bindings.remove("exit");
bindings.remove("quit");
System.err.println(engine.eval("'quit is ' + typeof quit"));
如果您使用的是Nashorn shell,则可以使用简单的delete quit;
。
如果您正在使用ScriptEngine界面并创建多个绑定,则必须对您创建的每个全局对象/绑定执行此操作。
答案 1 :(得分:3)
如果您要运行“不受信任”的脚本,请在安装了SecurityManager的情况下运行您的程序。随着“退出”将导致SecurityException。 ClassFilter本身不是SecurityManager的替代品。它用于与SecurityManager一起使用。请在此处查看ClassFilter上的JEP:http://openjdk.java.net/jeps/202。 JEP明确指出:
使安全管理员为脚本冗余。在评估来自不受信任来源的脚本之前,嵌入应用程序仍应启用安全性管理。单独的类过滤不会提供完整的脚本“沙箱”。即使只执行不受信任的脚本(没有其他Java类),仍应使用安全管理器。类过滤提供了超出安全管理器提供的更好的控制。例如,Nashorn嵌入应用程序可能会阻止线程从安全管理器可能允许的脚本或其他资源密集型操作中生成。