Sev*_*ich 9 java sandbox securitymanager
目前我正在尝试编写Sandbox来运行不受信任的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);
}
}
Run Code Online (Sandbox Code Playgroud)
显然,SM不能访问FileOutputStream并且不能更改方法中的内部变量(如名称或文件)或以某种方式影响执行顺序,除了抛出SecurityException.我明白,访问内部字段违反了面向对象的原则,我明白,局部变量是可见的,只存在于声明它们的方法中.
所以我的问题是:有没有办法让Security Manager替换对文件系统的调用?如果没有,我可以使用任何其他方法来做到这一点吗?
我希望我很清楚.
现在Java是开源的,您可以下载源代码FileOutputStream,修改其源代码以强制执行您希望的任何约束,重新编译它,将其添加到jar中,并将该JAR添加到JVM的引导加载程序类路径:
java -Xbootclasspath/p:myModifiedJavaClasses.jar sandbox.Main -run untrusted.Main
Run Code Online (Sandbox Code Playgroud)
JVM现在将使用您的实现java.io.FileOutputStream而不是通常的实现.对需要特殊沙盒重定向逻辑的所有JSE类进行冲洗和重复.
它不是最便携或易于部署的解决方案,因为它需要"在VM之外"修改启动参数,但在某些情况下,此解决方案可能是可接受且有效的.
SecurityManager不能这样做,它只能说是或否.
我可以想到两个选择:
使用文件系统在操作系统级别执行某些操作.chroot jails之类的东西.这对应用程序来说是透明的,但需要在Java之外工作.
为应用程序提供API,为其打开FileOutputStream.API层可以决定文件的来源,并且具有特权(在安全管理器术语中)可以从任何地方打开文件.当然,这要求沙盒应用程序使用您的API而不是java.io.File直接使用.但它也更加灵活,并在某些时候它可能是必要的应用程序需要注意的沙箱,并使用沙盒API,就像Java的Webstart的例如.