安全纳斯霍恩 JS 执行

2022-08-31 22:07:38

如何使用Java8 Nashorn安全地执行一些用户提供的JS代码?

该脚本扩展了一些基于 servlet 的报告的计算。该应用程序具有许多不同的(不受信任的)用户。脚本应该只能访问 Java 对象和由定义的成员返回的对象。默认情况下,脚本可以使用 Class.forName() 实例化任何类(使用我提供的对象的 .getClass()。有没有办法禁止访问任何未由我显式指定的java类?


答案 1

不久前,我在Nashorn邮件列表中问了这个问题

对于将 Nashorn 脚本可以创建的类限制为白名单的最佳方法,是否有任何建议?或者这种方法与任何JSR223引擎(ScriptEngineManager构造函数上的自定义类加载器)相同?

从Nashorn的一位开发人员那里得到了这个答案:

你好

  • Nashorn 已经筛选了类 - 只有非敏感包的公共类(包列在 package.access 安全属性(又名“敏感”)中)。包访问检查是从无权限上下文中完成的。也就是说,只允许从无权限类访问的任何包。

  • Nashorn 过滤 Java 反射和 jsr292 访问 - 除非脚本有 RuntimePermission(“nashorn.JavaReflection“),脚本将无法进行反射。

  • 上述两个需要在启用 SecurityManager 的情况下运行。在没有安全管理器的情况下,上述筛选将不适用。

  • 您可以在全局范围内删除全局Java.type函数和 Packages对象(+ com,edu,java,javafx,javax,org,JavaImporter)和/或将它们替换为您实现的任何过滤函数。因为,这些是从脚本访问 Java 的唯一入口点,自定义这些函数 = >从脚本中过滤 Java 访问。

  • 有一个未记录的选项(现在仅用于运行test262测试)“--no-java”的nashorn shell可以为您完成上述操作。也就是说,Nashorn不会在全局范围内初始化Java钩子。

  • JSR223 不提供任何基于标准的钩子来传递自定义类装入器。这可能必须在 jsr223 的(可能)未来更新中解决。

希望这有帮助,

-桑达尔


答案 2

1.8u40 中添加的 ClassFilter 可以限制引擎可以使用的类。

下面是 Oracle 文档中的一个示例:

import javax.script.ScriptEngine;
import jdk.nashorn.api.scripting.ClassFilter;
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
 
public class MyClassFilterTest {
 
  class MyCF implements ClassFilter {
    @Override
    public boolean exposeToScripts(String s) {
      if (s.compareTo("java.io.File") == 0) return false;
      return true;
    }
  }
 
  public void testClassFilter() {
 
    final String script =
      "print(java.lang.System.getProperty(\"java.home\"));" +
      "print(\"Create file variable\");" +
      "var File = Java.type(\"java.io.File\");";
 
    NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
 
    ScriptEngine engine = factory.getScriptEngine(
      new MyClassFilterTest.MyCF());
    try {
      engine.eval(script);
    } catch (Exception e) {
      System.out.println("Exception caught: " + e.toString());
    }
  }
 
  public static void main(String[] args) {
    MyClassFilterTest myApp = new MyClassFilterTest();
    myApp.testClassFilter();
  }
}

此示例打印以下内容:

C:\Java\jre8
Create file variable
Exception caught: java.lang.RuntimeException: java.lang.ClassNotFoundException:
java.io.File