versiones todas paquete las instalar esprit eliminar desinstalar descargar completo como borrar anteriores actualizaciones actualizacion java plugins sandbox

todas - eliminar actualizaciones java



Sandbox contra código malicioso en una aplicación Java (7)

  1. Ejecute el código que no es de confianza en su propio hilo. Esto, por ejemplo, previene problemas con bucles infinitos y demás, y facilita los pasos futuros. Haga que el hilo principal espere hasta que termine el hilo, y si tarda demasiado, elimínelo con Thread.stop. Thread.stop está en desuso, pero como el código que no es de confianza no debería tener acceso a ningún recurso, sería seguro matarlo.

  2. Establezca un SecurityManager en ese hilo. Cree una subclase de SecurityManager que anule checkPermission (Permiso permanente) para simplemente lanzar una SecurityException para todos los permisos excepto unos pocos. Hay una lista de métodos y los permisos que requieren aquí: Permisos en Java TM 6 SDK .

  3. Use un ClassLoader personalizado para cargar el código que no es de confianza. Su cargador de clases recibiría llamadas para todas las clases que usa el código que no es de confianza, por lo que puede hacer cosas como deshabilitar el acceso a clases JDK individuales. Lo que hay que hacer es tener una lista blanca de clases JDK permitidas.

  4. Es posible que desee ejecutar el código que no es de confianza en una JVM separada. Si bien los pasos anteriores protegerían el código, hay una cosa molesta que el código aislado aún puede hacer: asignar tanta memoria como sea posible, lo que hace que la huella visible de la aplicación principal crezca.

JSR 121: la especificación API de aislamiento de aplicaciones se diseñó para solucionar esto, pero desafortunadamente aún no tiene una implementación.

Este es un tema bastante detallado, y sobre todo estoy escribiendo esto fuera de mi cabeza.

Pero de todos modos, algunos imperfectos, use-at-your-own-risk, probablemente buggy (pseudo) código:

ClassLoader

class MyClassLoader extends ClassLoader { @Override public Class<?> loadClass(String name) throws ClassNotFoundException { if (name is white-listed JDK class) return super.loadClass(name); return findClass(name); } @Override public Class findClass(String name) { byte[] b = loadClassData(name); return defineClass(name, b, 0, b.length); } private byte[] loadClassData(String name) { // load the untrusted class data here } }

Gerente de seguridad

class MySecurityManager extends SecurityManager { private Object secret; public MySecurityManager(Object pass) { secret = pass; } private void disable(Object pass) { if (pass == secret) secret = null; } // ... override checkXXX method(s) here. // Always allow them to succeed when secret==null }

Hilo

class MyIsolatedThread extends Thread { private Object pass = new Object(); private MyClassLoader loader = new MyClassLoader(); private MySecurityManager sm = new MySecurityManager(pass); public void run() { SecurityManager old = System.getSecurityManager(); System.setSecurityManager(sm); runUntrustedCode(); sm.disable(pass); System.setSecurityManager(old); } private void runUntrustedCode() { try { // run the custom class''s main method for example: loader.loadClass("customclassname") .getMethod("main", String[].class) .invoke(null, new Object[]{...}); } catch (Throwable t) {} } }

En un entorno de servidor de simulación donde los usuarios pueden enviar su propio código para que el servidor lo ejecute, sería claramente ventajoso que cualquier código enviado por el usuario se ejecute en un entorno limitado, como sucede con los Applets en un navegador. Quería aprovechar la propia JVM, en lugar de agregar otra capa de VM para aislar estos componentes enviados.

Este tipo de limitación parece posible utilizando el modelo existente de sandbox de Java, pero ¿existe una forma dinámica de habilitarlo solo para las partes enviadas por el usuario de una aplicación en ejecución?


Aquí hay una solución segura para el problema:

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. }

¡Por favor comenta!

CU

Arno


Bueno, es muy tarde para dar cualquier sugerencia o solución, pero todavía estaba enfrentando un tipo similar de problema, más orientado a la investigación. Básicamente, estaba tratando de proporcionar una provisión y evaluaciones automáticas para las asignaciones de programación para el curso de Java en las plataformas de e-learning.

  1. Una de las formas podría ser Crear máquinas virtuales separadas (no JVM), pero máquinas virtuales reales con la configuración mínima posible del sistema operativo para cada uno de los estudiantes.
  2. Instale JRE para Java o bibliotecas de acuerdo con sus lenguajes de programación, lo que quiera que los estudiantes compilen y ejecuten en estas máquinas.

Sé que esto suena bastante complejo y con muchas tareas, pero Oracle Virtual Box ya proporciona API Java para crear o clonar máquinas virtuales de forma dinámica. https://www.virtualbox.org/sdkref/index.html (Nota, incluso VMware también proporciona API para hacer lo mismo)

Y para el tamaño mínimo y la distribución de Linux de configuración, puede consultar este aquí http://www.slitaz.org/en/ ,

Así que ahora si los estudiantes se equivocan o intentan hacerlo, puede ser con memoria o sistema de archivos o red, socket, máximo que puede dañar su propia máquina virtual.

También internamente en estas máquinas virtuales puede proporcionar seguridad adicional como Sandbox (administrador de seguridad) para Java o crear cuentas específicas del usuario en Linux y, por lo tanto, restringir el acceso.

Espero que esto ayude !!


Obviamente, tal esquema plantea todo tipo de preocupaciones de seguridad. Java tiene un marco de seguridad riguroso, pero no es trivial. No se debe pasar por alto la posibilidad de atornillarlo y dejar que un usuario sin privilegios acceda a componentes vitales del sistema.

Dejando a un lado esa advertencia, si está tomando la entrada del usuario en forma de código fuente, lo primero que debe hacer es compilarla en bytecode de Java. AFIAK, esto no se puede hacer de forma nativa, por lo que deberá realizar una llamada al sistema a javac y compilar el código fuente en bytecode en el disco. Here''s un tutorial que puede usarse como punto de partida para esto. Editar : como aprendí en los comentarios, puedes compilar el código Java desde el origen de forma nativa usando javax.tools.JavaCompiler

Una vez que tiene el bytecode de JVM, puede cargarlo en la JVM usando ClassLoader''s función de defineClass ClassLoader''s . Para establecer un contexto de seguridad para esta clase cargada, deberá especificar un ProtectionDomain . El constructor mínimo para un ProtectionDomain requiere un CodeSource y un PermissionCollection . El PermissionCollection es el objeto de uso principal para usted; puede usarlo para especificar los permisos exactos que tiene la clase cargada. Estos permisos deben ser aplicados en última instancia por AccessController la JVM.

Aquí hay muchos posibles puntos de error, y debe ser extremadamente cuidadoso para comprender completamente todo antes de implementar algo.


Para solucionar el problema en la respuesta aceptada según la cual el SecurityManager personalizado se aplicará a todos los hilos en la JVM, en lugar de hacerlo por subprocesos, puede crear un SecurityManager personalizado que se puede habilitar / deshabilitar para hilos específicos de la siguiente manera:

import java.security.Permission; public class SelectiveSecurityManager extends SecurityManager { private static final ToggleSecurityManagerPermission TOGGLE_PERMISSION = new ToggleSecurityManagerPermission(); ThreadLocal<Boolean> enabledFlag = null; public SelectiveSecurityManager(final boolean enabledByDefault) { enabledFlag = new ThreadLocal<Boolean>() { @Override protected Boolean initialValue() { return enabledByDefault; } @Override public void set(Boolean value) { SecurityManager securityManager = System.getSecurityManager(); if (securityManager != null) { securityManager.checkPermission(TOGGLE_PERMISSION); } super.set(value); } }; } @Override public void checkPermission(Permission permission) { if (shouldCheck(permission)) { super.checkPermission(permission); } } @Override public void checkPermission(Permission permission, Object context) { if (shouldCheck(permission)) { super.checkPermission(permission, context); } } private boolean shouldCheck(Permission permission) { return isEnabled() || permission instanceof ToggleSecurityManagerPermission; } public void enable() { enabledFlag.set(true); } public void disable() { enabledFlag.set(false); } public boolean isEnabled() { return enabledFlag.get(); } }

ToggleSecurirtyManagerPermission es solo una implementación simple de java.security.Permission para garantizar que solo el código autorizado pueda habilitar / deshabilitar el administrador de seguridad. Se parece a esto:

import java.security.Permission; public class ToggleSecurityManagerPermission extends Permission { private static final long serialVersionUID = 4812713037565136922L; private static final String NAME = "ToggleSecurityManagerPermission"; public ToggleSecurityManagerPermission() { super(NAME); } @Override public boolean implies(Permission permission) { return this.equals(permission); } @Override public boolean equals(Object obj) { if (obj instanceof ToggleSecurityManagerPermission) { return true; } return false; } @Override public int hashCode() { return NAME.hashCode(); } @Override public String getActions() { return ""; } }



Java-Sandbox es una biblioteca para ejecutar código Java con un conjunto limitado de permisos. Se puede usar para permitir el acceso solo a un conjunto de clases y recursos de la lista blanca. No parece ser capaz de restringir el acceso a métodos individuales. Utiliza un sistema con un cargador de clases personalizado y un administrador de seguridad para lograr esto.

No lo he usado, pero se ve bien diseñado y razonablemente bien documentado.

@waqas ha dado una respuesta muy interesante explicando cómo es posible implementarla usted mismo. Pero es mucho más seguro dejar tal código crítico y complejo de seguridad a los expertos.

Sin embargo, tenga en cuenta que el proyecto no se ha actualizado desde 2013 y los creadores lo describen como "experimental". Su página de inicio ha desaparecido pero permanece la entrada de Source Forge.

Ejemplo de código adaptado del sitio web del proyecto:

SandboxService sandboxService = SandboxServiceImpl.getInstance(); // Configure context SandboxContext context = new SandboxContext(); context.addClassForApplicationLoader(getClass().getName()); context.addClassPermission(AccessType.PERMIT, "java.lang.System"); // Whithout this line we get a SandboxException when touching System.out context.addClassPermission(AccessType.PERMIT, "java.io.PrintStream"); String someValue = "Input value"; class TestEnvironment implements SandboxedEnvironment<String> { @Override public String execute() throws Exception { // This is untrusted code System.out.println(someValue); return "Output value"; } }; // Run code in sandbox. Pass arguments to generated constructor in TestEnvironment. SandboxedCallResult<String> result = sandboxService.runSandboxed(TestEnvironment.class, context, this, someValue); System.out.println(result.get());