Java沙盒。使用SecurityManager重定向I/O访问

10

目前我正在尝试编写沙箱来运行不受信任的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的权限,也不能更改方法中的内部变量(如 name file ),或以其他方式影响执行顺序,除非抛出SecurityException。我确实明白,访问内部字段是违反面向对象原则的,我也明白,局部变量仅在声明它们的方法内部可见且存在。

所以我的问题是:有没有办法允许安全管理器替换对文件系统的调用?如果没有,我还能使用哪些其他方法来实现这一点?

希望我的表述足够清晰明了。

4个回答

6

SecurityManager无法实现此功能,它只能回答“是”或“否”。

我能想到两种选择:

  1. 在操作系统级别上使用文件系统进行某些操作。有像chroot jails这样的东西。这对应用程序来说是透明的,但需要在Java之外进行工作。

  2. 为应用程序提供API,以便为它们打开FileOutputStream。API层可以决定文件从哪里来,并且在安全管理器方面具有特权,可以从任何地方打开文件。当然,这要求受沙箱限制的应用程序使用您的API而不是直接使用java.io.File。但它也更加灵活,并且在某些情况下,应用程序必须意识到沙箱并使用沙箱API,就像在Java WebStart 例如中一样。


谢谢回答。第一个选项我不能接受,因为我不想限制自己只使用一个操作系统,但第二个选项看起来很不错。我搜索了一些API替代方案,并发现JMockit工具可以模拟类和存根。所以基本上我会研究一下它,我认为这就是我现在需要的。 - Sevich

6

现在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。我还在阅读更改以理解它哈哈 http://openjdk.java.net/jeps/261 - Jessy Diamond Exum

0

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

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

您想要做的应该在更低的级别上尝试,例如Linux的chroot和其他更重的虚拟化技术。


0

这篇文章并没有说类似的话。他们描述了一个SecurityManager,用于审计和可能禁止意外的I/O操作。禁止,而不是修改。 - Thilo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接