为什么我可以使用AccessController.doPrivileged打破受限制的AccessControlContext?

时间:2014-10-12 20:45:06

标签: java security access-control

我想知道如何在没有权限的情况下运行外部代码(来自不同的JAR),这样就不会损害我自己的系统。我几乎可以工作,但是我发现一个奇怪的情况,System.exit(0)的呼叫仍然会杀死整个系统。

我们的想法是在多线程环境中加载不同的JAR,因此System.exit(0)成功可能是服务器上许多其他安全风险中可能发生的最坏情况。

我有以下代码(在SSCEE中):

public class RestrictAccessControlContext {
    private static final PermissionCollection ALLOWED_PERMISSIONS = new Permissions();
    static {
        //add permissions
    }
    private static final AccessControlContext RESTRICTED_ACCESS_CONTROL_CONTEXT = 
        new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, ALLOWED_PERMISSIONS)});

    private static void executeSandboxed(final Runnable runnable) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future<?> future = executorService.submit(() -> {
            AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
                runnable.run();
                return null;
            }, RESTRICTED_ACCESS_CONTROL_CONTEXT);
        });
        try {
            future.get();
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        } catch (ExecutionException ex) {
            throw new RuntimeException(ex.getCause());
        } finally {
            executorService.shutdown();
        }
    }

    public static void main(String[] args) {
        executeSandboxed(() -> {
            AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
                System.exit(0);
                return null;
            });
        });
    }
}

需要以VM参数运行:

  

-Djava.security.manager -Djava.security.policy = src / java.policy

java.policy的位置:

grant {
    permission java.security.AllPermission;
};

我的想法是我自己的代码仍然具有完全权限,但沙盒代码限制了(在本例中为:none)权限。

但是在给定的示例中它只是退出,请注意主方法的以下变体工作:

public static void main(String[] args) {
    executeSandboxed(() -> System.exit(0));
}

public static void main(String[] args) {
    executeSandboxed(() -> new Thread(() -> System.exit(0)).start());
}

我在这里做错了什么,为什么可以执行AccessController.doPrivileged调用来提升权限,当它们受到限制之前?我希望下列之一是真的:

  1. 可能会有一个特定的权限来调用AccessController.doPrivileged
  2. AccessController.doPrivileged块中,权限将是&#34; parent&#34; AccessControlContext和给定的许可。
  3. 这两个选项都会导致给定的代码正确抛出AccessControlException,但它不会发生,为什么会这样呢?

1 个答案:

答案 0 :(得分:1)

您没有任何沙盒代码。您的代码具有完全权限,正在使用它们。没有相关许可的代码将无法退出。解决方案应该是使用不受信任的ProtectionDomain加载不受信任的代码。

获得许可是非常有意义的。这相当于拥有所有权限。

在OpenJDK内部,有doPrivileged的变体允许权限交叉,但这是为了在存在多个不信任来源时降低权限。