Java 沙盒和 ProcessBuilder

Posted

技术标签:

【中文标题】Java 沙盒和 ProcessBuilder【英文标题】:Java Sandboxing and ProcessBuilder 【发布时间】:2018-07-04 13:40:17 【问题描述】:

我按照tutorial 为插件代码实现了 java 沙盒。插件代码使用以下权限运行:

private PermissionCollection pluginPermissions() 
    Permissions permissions = new Permissions(); 
    permissions.add(new FilePermission("/projects", "read,write,execute"));
    return permissions;
  

它工作正常。但是,我想允许插件启动一个进程,该进程也将受到这些权限的限制。例如,它应该能够通过运行这个命令“python test.py”来运行一个python脚本,只要该脚本在/projects目录中并且它不访问其他任何地方。就像下面的代码,其中 cmnd 是“python”,mainFilePath 是 python 脚本,它位于限制进程的目录中。

public static File startProcess(String cmnd, String mainFilePath, String directory)
        try 
            ProcessBuilder pb =
                    new ProcessBuilder( cmnd, mainFilePath);

            pb.directory(new File(directory));
            File f = pb.directory();
            System.out.println(f.exists());

            File log = new File(directory,"log.txt");

            pb.redirectErrorStream(true);
            pb.redirectOutput(ProcessBuilder.Redirect.appendTo(log));

            Process p = pb.start();
            return log;
        catch (Exception e)
            e.printStackTrace();
        
        return null;
    

如果我从插件运行此代码,我会收到以下异常:

java.security.AccessControlException: access denied ("java.io.FilePermission" "<<ALL FILES>>" "execute")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
    at java.security.AccessController.checkPermission(AccessController.java:884)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    at java.lang.SecurityManager.checkExec(SecurityManager.java:799)
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1018)
    at engine.LogHelper.startProcess(LogHelper.java:28)
    at engine.ZEngine.build(ZEngine.java:13)
    at Main.main(Main.java:29)

这表明我需要对所有文件授予“执行”权限。但我只需要对指定目录中的文件进行该限制。那么如何在允许ProcessBuilder在受限目录下启动进程的同时实现沙盒呢?

更新:

插件权限现在如下:

permissions.add(new FilePermission("/Users/ziadalhalabi/IdeaProjects/JarDummy/projects/-", "read,write"));            
permissions.add(new FilePermission("/Users/ziadalhalabi/IdeaProjects/JarDummy/projects/", "read,write,execute"));     
permissions.add(new FilePermission("/usr/local/bin/python", "execute"));

它可以工作,但 python 脚本能够读取目录之外的文件。我想将沙箱应用于 python 脚本中的任何内容。

【问题讨论】:

Java 无法限制另一个进程可以做什么。只有操作系统可以限制这一点,因此您需要以仅具有您希望授予它的任何访问权限的用户身份运行该进程。如何做到这一点将是serverfault.com 的问题 谢谢@Andreas,这很有帮助! 【参考方案1】:

您运行命令python(不合格),所以start() 不知道文件在哪里,因此请检查您是否被允许execute 访问&lt;&lt;ALL FILES&gt;&gt;。既然你不是,那就被拒绝了。

如果您指定python 的完整(绝对)路径授予对python 文件的访问权限,它将起作用。

有关权限检查的说明,请参见SecurityManager.checkExec​(String cmd) 的 javadoc:

如果不允许调用线程创建子进程,则抛出SecurityException

此方法由Runtime 类的exec 方法为当前安全管理器调用。

该方法调用checkPermission,权限为FilePermission(cmd,"execute")如果cmd是绝对路径,否则调用checkPermission,权限为FilePermission("&lt;&lt;ALL FILES&gt;&gt;","execute")

【讨论】:

感谢@Andreas 的回答。请查看我对这个问题的更新。

以上是关于Java 沙盒和 ProcessBuilder的主要内容,如果未能解决你的问题,请参考以下文章

Mac 沙盒和临时文件

将推送证书从 2 个(沙盒和生产)更改为 1 个证书(沙盒/生产)

Mac 应用程序沙盒和 forkpty()

沙盒和简单的对象的写入和读取(预习)

Mac 沙盒和文件 ioctl

沙盒和App Group