48

Java8 Nashorn を使用して、ユーザー提供の JS コードを安全に実行するにはどうすればよいですか?

このスクリプトは、一部のサーブレット ベースのレポートの一部の計算を拡張します。アプリにはさまざまな (信頼されていない) ユーザーがいます。スクリプトは、Java オブジェクトと、定義されたメンバーによって返されたオブジェクトにのみアクセスできる必要があります。デフォルトでは、スクリプトは Class.forName() (提供されたオブジェクトの .getClass() を使用) を使用して任意のクラスをインスタンス化できます。私が明示的に指定していない Java クラスへのアクセスを禁止する方法はありますか?

4

9 に答える 9

26

しばらく前に、Nashorn メーリング リストで次の質問をしました。

Nashorn スクリプトが作成できるクラスをホワイトリストに制限するための最善の方法に関する推奨事項はありますか? それとも、アプローチは JSR223 エンジン (ScriptEngineManager コンストラクターのカスタム クラスローダー) と同じですか?

Nashorn 開発者の 1 人から次の回答を得ました。

やあ、

  • Nashorn は既にクラスをフィルター処理しています。機密でないパッケージ (package.access セキュリティ プロパティ、別名「機密」にリストされているパッケージ) のパブリック クラスのみです。パッケージ アクセス チェックは、権限のないコンテキストから実行されます。つまり、権限のないクラスからアクセスできるパッケージはすべて許可されます。

  • Nashorn は、Java リフレクションおよび jsr292 アクセスをフィルター処理します。スクリプトに RuntimePermission("nashorn.JavaReflection") がない限り、スクリプトはリフレクションを実行できません。

  • 上記の 2 つは、SecurityManager を有効にして実行する必要があります。セキュリティ マネージャがない場合、上記のフィルタリングは適用されません。

  • グローバル スコープでグローバル Java.type 関数と Packages オブジェクト (+ com、edu、java、javafx、javax、org、JavaImporter) を削除したり、実装するフィルタリング関数に置き換えたりすることができます。これらはスクリプトからの Java アクセスへの唯一のエントリ ポイントであるため、これらの関数をカスタマイズする => スクリプトからの Java アクセスをフィルタリングします。

  • 文書化されていないオプション (現在は test262 テストを実行するためだけに使用されます) があり、上記を実行する nashorn シェルの "--no-java" があります。つまり、Nashorn はグローバル スコープで Java フックを初期化しません。

  • JSR223 は、カスタム クラス ローダーを渡すための標準ベースのフックを提供しません。これは、jsr223 の (可能性のある) 将来の更新で対処する必要があるかもしれません。

お役に立てれば、

-サンダー

于 2014-05-25T00:43:43.130 に答える
20

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
于 2015-11-16T15:48:28.247 に答える
7

ClassFilterJavaScript で使用できる Java クラスをきめ細かく制御できる を簡単に作成できます。

Oracle Nashorn Docsの例に従います。

class MyCF implements ClassFilter {
    @Override
    public boolean exposeToScripts(String s) {
      if (s.compareTo("java.io.File") == 0) return false;
      return true;
    }
}

今日、私はこれを他のいくつかの方法で小さなライブラリにまとめました: Nashorn Sandbox (GitHub 上)。楽しみ!

于 2015-08-07T05:05:48.087 に答える
6

私の知る限り、Nashorn をサンドボックス化することはできません。信頼されていないユーザーは、ここにリストされている「追加の Nashorn 組み込み関数」を実行できます。

https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/shell.html

これには「quit()」が含まれます。私はそれをテストしました。JVM を完全に終了します。

(余談ですが、私のセットアップでは、グローバル オブジェクト $ENV、$ARG が機能しませんでした。これは良いことです。)

私がこれについて間違っている場合は、誰かコメントを残してください。

于 2015-06-30T00:12:24.140 に答える
0

独自の ClassLoader と SecurityManager を実装したくない場合は、外部のサンドボックス ライブラリを使用できます (現時点ではこれがサンドボックス化の唯一の方法です)。

「The Java Sandbox」( http://blog.datenwerke.net/p/the-java-sandbox.html )を試してみましたが、端が少し荒いですが、機能します。

于 2014-05-15T23:10:30.900 に答える