如何在沙盒中使用Rhino for Java运行Javascript?

时间:2022-06-24 21:09:20

Part of our java application needs to run javascript that is written by non-developers. These non-developers are using javascript for data formatting. (Simple logic and string concatenation mostly).

我们的Java应用程序的一部分需要运行由非开发人员编写的javascript。这些非开发人员使用javascript进行数据格式化。 (主要是简单的逻辑和字符串连接)。

My question is how can I setup the execution of these scripts to make sure scripting errors don't have a major negative impact on the rest of the application.

我的问题是如何设置这些脚本的执行以确保脚本错误不会对应用程序的其余部分产生重大负面影响。

  • Need to guard against infinite loops
  • 需要防范无限循环

  • Guard against spawning new threads.
  • 防止产生新线程。

  • Limit access to services and environment
    • File system (Example: If a disgruntled script writer decided to delete files)
    • 文件系统(示例:如果心怀不满的脚本编写者决定删除文件)

    • Database (Same thing delete database records)
    • 数据库(同样删除数据库记录)

  • 限制访问服务和环境文件系统(例如:如果心怀不满的脚本编写者决定删除文件)数据库(同样的事情删除数据库记录)

Basically I need to setup the javascript scope to only include exactly what they need and no more.

基本上我需要设置javascript范围,只包括他们需要的内容,而不是更多内容。

6 个解决方案

#1


9  

To guard against infinite loops, you'd need to put it in a separate process so that it could be killed.

为了防止无限循环,你需要将它放在一个单独的进程中,以便它可以被杀死。

To guard against creating threads, you'd need to extend SecurityManager (the default implementation allows untrusted code to access non-root thread groups).

为了防止创建线程,您需要扩展SecurityManager(默认实现允许不受信任的代码访问非根线程组)。

Java security does allow you to prevent access to the file system.

Java安全性允许您阻止访问文件系统。

For database restrictions, you might be able to use the standard SQL user security, but that is quite weak. Otherwise, you need to provide an API that enforces your restrictions.

对于数据库限制,您可能可以使用标准SQL用户安全性,但这非常弱。否则,您需要提供一个强制执行限制的API。

Edit: I should point out that the version of Rhino provided with JDK6 has had security work done on it, but doesn't include the compiler.

编辑:我应该指出,JDK6提供的Rhino版本已经完成了安全工作,但不包括编译器。

#2


20  

To guard against infinite loops, you can observe the instruction count as the script runs (this works only with interpreted scripts, not with compiled ones).

为了防止无限循环,您可以在脚本运行时观察指令计数(这仅适用于已解释的脚本,而不适用于已编译的脚本)。

There is this example in the Rhino JavaDocs to prevent a script from running for more than ten seconds:

Rhino JavaDocs中有一个例子可以防止脚本运行超过十秒:

 protected void observeInstructionCount(Context cx, int instructionCount)
 {
     MyContext mcx = (MyContext)cx;
     long currentTime = System.currentTimeMillis();
     if (currentTime - mcx.startTime > 10*1000) {
         // More then 10 seconds from Context creation time:
         // it is time to stop the script.
         // Throw Error instance to ensure that script will never
         // get control back through catch or finally.
         throw new Error();
     }
 }

#3


13  

To block Java class and method access have a look at...

要阻止Java类和方法访问,请看...

http://codeutopia.net/blog/2009/01/02/sandboxing-rhino-in-java/

#4


1  

I just ran across this blog post that seems to be useful for sandboxing more or less anything (not just Rhino):

我刚刚浏览了这篇博文,似乎对沙箱或多或少的任何东西都有用(不仅仅是Rhino):

http://calumleslie.blogspot.com/2008/06/simple-jvm-sandboxing.html

#5


0  

If you are looking for pure JavaScript functions only, here is a solution basing on JDK embedded Rhino library without importing any 3rd-parties libraries:

如果您只是寻找纯JavaScript函数,这里是一个基于JDK嵌入式Rhino库的解决方案,无需导入任何第三方库:

  1. Find out JavaScript script engine factory class name by ScriptEngineManager#getEngineFactories
  2. 通过ScriptEngineManager#getEngineFactories找出JavaScript脚本引擎工厂类名

  3. Load script engine factory class in a new class loader, in which JavaMembers or other related classes will be ignored.
  4. 在新的类加载器中加载脚本引擎工厂类,其中将忽略JavaMembers或其他相关类。

  5. Call #getScriptEngine on loaded script engine factory and eval scripts on returned script engine.
  6. 在已加载的脚本引擎工厂上调用#getScriptEngine,在返回的脚本引擎上调用eval脚本。

If given script contains Java script, class loader will try to load JavaMembers or other classes and trigger class not found exceptions. In this way, malicious scripts will be ignored without execution.

如果给定脚本包含Java脚本,则类加载器将尝试加载JavaMembers或其他类并触发类未找到的异常。这样,恶意脚本将被忽略而不执行。

Please read ConfigJSParser.java and ConfigJSClassLoader.java files for more details:

有关更多详细信息,请阅读ConfigJSParser.java和ConfigJSClassLoader.java文件:

https://github.com/webuzz/simpleconfig/tree/master/src/im/webuzz/config

#6


-9  

Javascript is single-threaded and can't access the filesystem, so I don't think you have to worry about those. I'm not sure if there's a way to set a timeout to guard against infinite loops, but you could always spawn a (Java) thread that executes the script, and then kill the thread after so much time.

Javascript是单线程的,无法访问文件系统,所以我认为你不必担心这些。我不确定是否有办法设置超时以防止无限循环,但你总是可以生成一个执行脚本的(Java)线程,然后在这么多时间后终止线程。

#1


9  

To guard against infinite loops, you'd need to put it in a separate process so that it could be killed.

为了防止无限循环,你需要将它放在一个单独的进程中,以便它可以被杀死。

To guard against creating threads, you'd need to extend SecurityManager (the default implementation allows untrusted code to access non-root thread groups).

为了防止创建线程,您需要扩展SecurityManager(默认实现允许不受信任的代码访问非根线程组)。

Java security does allow you to prevent access to the file system.

Java安全性允许您阻止访问文件系统。

For database restrictions, you might be able to use the standard SQL user security, but that is quite weak. Otherwise, you need to provide an API that enforces your restrictions.

对于数据库限制,您可能可以使用标准SQL用户安全性,但这非常弱。否则,您需要提供一个强制执行限制的API。

Edit: I should point out that the version of Rhino provided with JDK6 has had security work done on it, but doesn't include the compiler.

编辑:我应该指出,JDK6提供的Rhino版本已经完成了安全工作,但不包括编译器。

#2


20  

To guard against infinite loops, you can observe the instruction count as the script runs (this works only with interpreted scripts, not with compiled ones).

为了防止无限循环,您可以在脚本运行时观察指令计数(这仅适用于已解释的脚本,而不适用于已编译的脚本)。

There is this example in the Rhino JavaDocs to prevent a script from running for more than ten seconds:

Rhino JavaDocs中有一个例子可以防止脚本运行超过十秒:

 protected void observeInstructionCount(Context cx, int instructionCount)
 {
     MyContext mcx = (MyContext)cx;
     long currentTime = System.currentTimeMillis();
     if (currentTime - mcx.startTime > 10*1000) {
         // More then 10 seconds from Context creation time:
         // it is time to stop the script.
         // Throw Error instance to ensure that script will never
         // get control back through catch or finally.
         throw new Error();
     }
 }

#3


13  

To block Java class and method access have a look at...

要阻止Java类和方法访问,请看...

http://codeutopia.net/blog/2009/01/02/sandboxing-rhino-in-java/

#4


1  

I just ran across this blog post that seems to be useful for sandboxing more or less anything (not just Rhino):

我刚刚浏览了这篇博文,似乎对沙箱或多或少的任何东西都有用(不仅仅是Rhino):

http://calumleslie.blogspot.com/2008/06/simple-jvm-sandboxing.html

#5


0  

If you are looking for pure JavaScript functions only, here is a solution basing on JDK embedded Rhino library without importing any 3rd-parties libraries:

如果您只是寻找纯JavaScript函数,这里是一个基于JDK嵌入式Rhino库的解决方案,无需导入任何第三方库:

  1. Find out JavaScript script engine factory class name by ScriptEngineManager#getEngineFactories
  2. 通过ScriptEngineManager#getEngineFactories找出JavaScript脚本引擎工厂类名

  3. Load script engine factory class in a new class loader, in which JavaMembers or other related classes will be ignored.
  4. 在新的类加载器中加载脚本引擎工厂类,其中将忽略JavaMembers或其他相关类。

  5. Call #getScriptEngine on loaded script engine factory and eval scripts on returned script engine.
  6. 在已加载的脚本引擎工厂上调用#getScriptEngine,在返回的脚本引擎上调用eval脚本。

If given script contains Java script, class loader will try to load JavaMembers or other classes and trigger class not found exceptions. In this way, malicious scripts will be ignored without execution.

如果给定脚本包含Java脚本,则类加载器将尝试加载JavaMembers或其他类并触发类未找到的异常。这样,恶意脚本将被忽略而不执行。

Please read ConfigJSParser.java and ConfigJSClassLoader.java files for more details:

有关更多详细信息,请阅读ConfigJSParser.java和ConfigJSClassLoader.java文件:

https://github.com/webuzz/simpleconfig/tree/master/src/im/webuzz/config

#6


-9  

Javascript is single-threaded and can't access the filesystem, so I don't think you have to worry about those. I'm not sure if there's a way to set a timeout to guard against infinite loops, but you could always spawn a (Java) thread that executes the script, and then kill the thread after so much time.

Javascript是单线程的,无法访问文件系统,所以我认为你不必担心这些。我不确定是否有办法设置超时以防止无限循环,但你总是可以生成一个执行脚本的(Java)线程,然后在这么多时间后终止线程。