【问题标题】:Java sandbox. Using SecurityManager to redirect I/O accessJava沙箱。使用 SecurityManager 重定向 I/O 访问
【发布时间】:2011-05-18 09:11:37
【问题描述】:

目前我正在尝试编写沙盒以运行不受信任的 Java 代码。这个想法是将 Java 应用程序与访问文件系统或网络套接字隔离开来。我目前的解决方案是重写 SecurityManager,它禁止对 IO 或网络的任何访问。

现在我不想禁止,而是将调用重定向到文件系统,即如果应用程序想要写入 "/home/user/application.txt" 文件的路径应该是替换为 "/temp/trusted_folder/application.txt" 之类的内容。所以基本上我想允许应用程序只访问某个特定文件夹中的文件系统,并将所有其他调用重定向到这个文件夹。

所以这是 FileOutputStream 类中的方法,其中询问 SM,是否有写入给定路径的权限。

 public FileOutputStream(File file, boolean append)
    throws FileNotFoundException
{
    String name = (file != null ? file.getPath() : null);
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkWrite(name);
    }
    if (name == null) {
        throw new NullPointerException();
    }
    fd = new FileDescriptor();
    fd.incrementAndGetUseCount();
    this.append = append;
    if (append) {
        openAppend(name);
    } else {
        open(name);
    }
}

显然,SM 无法访问 FileOutputStream,也无法更改方法中的内部变量(如 namefile)或以某种方式影响执行顺序,除非抛出安全异常。我明白,访问内部字段违反了面向对象的原则,我明白,局部变量是可见的,并且只存在于声明它们的方法内部。

所以我的问题是:有什么方法可以让安全管理器替换对文件系统的调用?如果没有,我可以使用其他方法来做到这一点吗?

我希望我已经足够清楚了。

【问题讨论】:

    标签: java sandbox securitymanager


    【解决方案1】:

    SecurityManager 不能这样做,它只能说是或否。

    我能想到两个选择:

    1. 在文件系统的操作系统级别上做一些事情。有chroot jails 之类的东西。这对应用程序来说是透明的,但需要在 Java 之外工作。

    2. 为应用程序提供一个 API,为他们打开 FileOutputStream。 API 层可以决定文件的来源,并且有权(在安全管理器术语中)从任何地方打开文件。当然,这要求沙盒应用程序直接使用您的 API 而不是 java.io.File。但它也更加灵活,在某些时候,应用程序可能需要了解沙盒并使用沙盒 API,就像在 Java WebStart for example 上一样。

    【讨论】:

    • 感谢您的回答。第一个选项我不能接受,因为我不想将自己限制在一个操作系统上,但第二个选项看起来相当不错。我搜索了一些 API 替换,发现 JMockit 工具可以模拟类和做存根。所以基本上我会调查它,我认为这就是我现在需要的。
    【解决方案2】:

    我认为这是不可能的。 安全管理器旨在拒绝对特定操作的访问,而不是重定向 IO 或做其他类似的事情。

    即使可以通过一些严重的反射黑客攻击,它也可能无法在不同的 jvm 供应商甚至运行相同 jvm 的不同操作系统之间移植。 (那是因为您需要操作特定于操作系统的类)。

    您想要做的事情应该在较低级别进行尝试,请参阅 chroot for linux 和其他更重的虚拟化技术。

    【讨论】:

      【解决方案3】:

      我认为您正在尝试做的事情已经由 Wealthfront 的工程师实施。
      这是他们的博客文章:http://eng.wealthfront.com/2010/11/less-io-for-your-java-unit-tests.html

      【讨论】:

      • 文章中没有这样说。他们正在描述一个 SecurityManager 审计并可能禁止意外的 I/O 操作。不允许,而不是修改。
      【解决方案4】:

      现在 Java 是开源的,您可以将源代码下载到 FileOutputStream,修改其源代码以强制执行您希望的任何约束,重新编译它,将其添加到 jar 中,并将该 JAR 预先添加到 JVM 的引导加载程序类路径中:

      java -Xbootclasspath/p:myModifiedJavaClasses.jar sandbox.Main -run untrusted.Main
      

      JVM 现在将使用您的java.io.FileOutputStream 实现而不是通常的实现。对需要特殊沙盒重定向逻辑的所有 JSE 类进行冲洗和重复。

      它不是最便携或最容易部署的解决方案,因为它需要“在 VM 之外”修​​改启动参数,但在某些情况下,此解决方案可能是可接受且有效的。

      【讨论】:

      • 我自己使用这个,但是在 Java9 中,Xbootclasspath 和 Xbootclasspath/p 已被删除。现在应该使用 --patch-module 。仍在阅读更改以了解它 lol openjdk.java.net/jeps/261
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-27
      • 1970-01-01
      相关资源
      最近更新 更多