52

プラグインとも呼ばれる他の人のコードを実行するアプリケーションを作成したいと考えています。ただし、悪意のあるコードを記述しないように、これを安全にするためにどのようなオプションが必要ですか。彼らができること、またはできないことをどのように制御できますか?

JVM には「ビルトイン サンドボックス」機能があることに出くわしました。それは何ですか?これが唯一の方法ですか? サンドボックスを作成するためのサードパーティの Java ライブラリはありますか?

どのようなオプションがありますか? ガイドと例へのリンクは大歓迎です!

4

7 に答える 7

26

セキュリティマネージャーを探しています。ポリシーを指定して、アプリケーションの権限を制限できます。

于 2009-11-11T13:06:52.897 に答える
19
  • 独自のセキュリティ マネージャを定義して登録すると、コードの動作を制限できます。SecurityManager については、Oracle のドキュメントを参照してください

  • また、コードをロードするための別のメカニズムを作成することを検討してください。つまり、特別な場所からコードをロードする別のクラスローダーを作成またはインスタンス化することができます。コードをロードするための規則がある場合があります。たとえば、特別なディレクトリから、または特別にフォーマットされた zip ファイル (WAR ファイルおよび JAR ファイルとして) からです。クラスローダーを作成している場合、コードをロードするために作業を行う必要があります。これは、拒否したいもの (または何らかの依存関係) を見つけた場合、単純にコードのロードに失敗する可能性があることを意味します。http://java.sun.com/javase/6/docs/api/java/lang/ClassLoader.html

于 2009-11-11T13:16:26.027 に答える
7

信頼されていないコードを実行する非常に柔軟なサンドボックスを簡単に作成できるjava-sandbox プロジェクトを見てください。

于 2013-06-13T05:36:31.367 に答える
4

AppContextAWT/Swing アプリケーションでは、いつでも変更される可能性がある非標準クラスを使用する必要があります。したがって、効果的にするには、別のプロセスを開始してプラグイン コードを実行し、2 つの間の通信を処理する必要があります (Chrome に少し似ています)。プラグイン プロセスには、プラグイン コードを分離し、適切なをプラグイン クラスに適用するために、 SecurityManagerset と aが必要です。ClassLoaderProtectionDomain

于 2009-11-11T13:31:29.160 に答える
3

SecurityManager を使用して問題を解決する方法は次のとおりです。

https://svn.code.sf.net/p/loggifier/code/trunk/de.unkrig.commons.lang/src/de/unkrig/commons/lang/security/Sandbox.java

package de.unkrig.commons.lang.security;

import java.security.AccessControlContext;
import java.security.Permission;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;

import de.unkrig.commons.nullanalysis.Nullable;

/**
 * This class establishes a security manager that confines the permissions for code executed through specific classes,
 * which may be specified by class, class name and/or class loader.
 * <p>
 * To 'execute through a class' means that the execution stack includes the class. E.g., if a method of class {@code A}
 * invokes a method of class {@code B}, which then invokes a method of class {@code C}, and all three classes were
 * previously {@link #confine(Class, Permissions) confined}, then for all actions that are executed by class {@code C}
 * the <i>intersection</i> of the three {@link Permissions} apply.
 * <p>
 * Once the permissions for a class, class name or class loader are confined, they cannot be changed; this prevents any
 * attempts (e.g. of the confined class itself) to release the confinement.
 * <p>
 * Code example:
 * <pre>
 *  Runnable unprivileged = new Runnable() {
 *      public void run() {
 *          System.getProperty("user.dir");
 *      }
 *  };
 *
 *  // Run without confinement.
 *  unprivileged.run(); // Works fine.
 *
 *  // Set the most strict permissions.
 *  Sandbox.confine(unprivileged.getClass(), new Permissions());
 *  unprivileged.run(); // Throws a SecurityException.
 *
 *  // Attempt to change the permissions.
 *  {
 *      Permissions permissions = new Permissions();
 *      permissions.add(new AllPermission());
 *      Sandbox.confine(unprivileged.getClass(), permissions); // Throws a SecurityException.
 *  }
 *  unprivileged.run();
 * </pre>
 */
public final
class Sandbox {

    private Sandbox() {}

    private static final Map<Class<?>, AccessControlContext>
    CHECKED_CLASSES = Collections.synchronizedMap(new WeakHashMap<Class<?>, AccessControlContext>());

    private static final Map<String, AccessControlContext>
    CHECKED_CLASS_NAMES = Collections.synchronizedMap(new HashMap<String, AccessControlContext>());

    private static final Map<ClassLoader, AccessControlContext>
    CHECKED_CLASS_LOADERS = Collections.synchronizedMap(new WeakHashMap<ClassLoader, AccessControlContext>());

    static {

        // Install our custom security manager.
        if (System.getSecurityManager() != null) {
            throw new ExceptionInInitializerError("There's already a security manager set");
        }
        System.setSecurityManager(new SecurityManager() {

            @Override public void
            checkPermission(@Nullable Permission perm) {
                assert perm != null;

                for (Class<?> clasS : this.getClassContext()) {

                    // Check if an ACC was set for the class.
                    {
                        AccessControlContext acc = Sandbox.CHECKED_CLASSES.get(clasS);
                        if (acc != null) acc.checkPermission(perm);
                    }

                    // Check if an ACC was set for the class name.
                    {
                        AccessControlContext acc = Sandbox.CHECKED_CLASS_NAMES.get(clasS.getName());
                        if (acc != null) acc.checkPermission(perm);
                    }

                    // Check if an ACC was set for the class loader.
                    {
                        AccessControlContext acc = Sandbox.CHECKED_CLASS_LOADERS.get(clasS.getClassLoader());
                        if (acc != null) acc.checkPermission(perm);
                    }
                }
            }
        });
    }

    // --------------------------

    /**
     * All future actions that are executed through the given {@code clasS} will be checked against the given {@code
     * accessControlContext}.
     *
     * @throws SecurityException Permissions are already confined for the {@code clasS}
     */
    public static void
    confine(Class<?> clasS, AccessControlContext accessControlContext) {

        if (Sandbox.CHECKED_CLASSES.containsKey(clasS)) {
            throw new SecurityException("Attempt to change the access control context for '" + clasS + "'");
        }

        Sandbox.CHECKED_CLASSES.put(clasS, accessControlContext);
    }

    /**
     * All future actions that are executed through the given {@code clasS} will be checked against the given {@code
     * protectionDomain}.
     *
     * @throws SecurityException Permissions are already confined for the {@code clasS}
     */
    public static void
    confine(Class<?> clasS, ProtectionDomain protectionDomain) {
        Sandbox.confine(
            clasS,
            new AccessControlContext(new ProtectionDomain[] { protectionDomain })
        );
    }

    /**
     * All future actions that are executed through the given {@code clasS} will be checked against the given {@code
     * permissions}.
     *
     * @throws SecurityException Permissions are already confined for the {@code clasS}
     */
    public static void
    confine(Class<?> clasS, Permissions permissions) {
        Sandbox.confine(clasS, new ProtectionDomain(null, permissions));
    }

    // Code for 'CHECKED_CLASS_NAMES' and 'CHECKED_CLASS_LOADERS' omitted here.

}
于 2014-06-14T23:10:29.237 に答える