50 votes

Comment créer un sandbox java?

Je veux faire mon application pour exécuter le code d'autres personnes, aka plugins. Cependant, quelles sont les options dont je dispose pour sécuriser ce lieu afin qu’ils n’écrivent pas de code malveillant. Comment puis-je contrôler ce qu'ils peuvent ou ne peuvent pas faire?

J'ai trouvé par hasard que la machine virtuelle Java dispose d'une fonctionnalité "construit dans le bac à sable" - qu'est-ce que c'est et est-ce le seul moyen? Existe-t-il des bibliothèques Java tierces pour créer un bac à sable?

Quelles sont mes options? Les liens vers des guides et des exemples sont appréciés!

25voto

tangens Points 17733

Vous recherchez un responsable de la sécurité . Vous pouvez limiter les autorisations d'une application en spécifiant une stratégie .

19voto

daf Points 5180
  • Définition et d'enregistrement de votre propre gestionnaire de sécurité vous permettra de limiter ce que fait le code - voir la documentation d'oracle pour SecurityManager.

  • Aussi, envisager la création d'un mécanisme distinct pour le chargement du code - à-d. vous pouvez écrire ou instancier un autre chargeur de classe pour charger le code à partir d'un endroit spécial. Vous pourriez avoir une convention pour le chargement du code - par exemple à partir d'un répertoire ou d'un format de fichier zip (comme la GUERRE de fichiers et les fichiers JAR). Si vous êtes à la rédaction d'un chargeur de classe, il vous met dans la position d'avoir à faire le travail pour obtenir le code chargé. Cela signifie que si vous voyez quelque chose (ou de certains de dépendance) vous souhaitez rejeter, vous pouvez tout simplement ne pas charger le code. http://java.sun.com/javase/6/docs/api/java/lang/ClassLoader.html

6voto

acerberus Points 583

Jetez un coup d'œil au projet java-sandbox qui permet de créer facilement des sandbox très flexibles pour exécuter du code non fiable.

4voto

Pour une application AWT / Swing, vous devez utiliser une classe non standard AppContext , qui peut changer à tout moment. Donc, pour être efficace, vous devez démarrer un autre processus pour exécuter du code de plug-in et gérer la communication entre les deux (un peu comme Chrome). Le processus de plug-in nécessite un ensemble SecurityManager et un ClassLoader pour isoler le code du plug-in et appliquer un ProtectionDomain approprié aux classes de plug-in.

3voto

Arno Unkrig Points 11

Voici comment résoudre le problème avec un 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.

}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X