我有一个Java/Scala应用程序,它执行磁盘IO并动态加载用户提交的类。动态类在它们自己的ClassLoaders下运行。
在加载这些类时应该考虑哪些安全问题,以确保它们没有删除磁盘文件或执行任何恶意操作的权限,并且只是在执行内存中的操作?
我到目前为止做了什么,
java.io.*、java.nio.*、java.lang.reflect和java.lang.Runtime.*相关的导入。我试图看看这些导入是否可以直接从类路径中删除,而不是执行regex操作。另一种选择是在它们自己的JVM进程中运行它们,并为每个进程设置文件系统(Linux)级别的权限,但这并不适合我的解决方案,因为我需要它们共享线程安全的内存对象。
有人能不能建议一下,如果我走上了正确的轨道,还应该考虑些什么?
发布于 2018-08-25 12:56:43
正如@Kayaman所说,您应该尝试使用SecurityManager处理这些动态类-- permissions,这里有一个很小的例子来演示这一点,也许这对您有帮助。
1.创建动态类策略文件,这将用于限制权限,例如my.policy
grant {
permission java.io.FilePermission "*", "read";
};上述策略将为任何文件启用读取文件。
2.创建自定义策略文件,用于处理具有权限验证规则的动态类。
class MyPolicy extends Policy {
//custom classes with policy mapping
private final Map<String, Policy> plugins;
MyPolicy(Map<String, Policy> plugins) {
this.plugins = plugins;
}
@Override
public boolean implies(ProtectionDomain domain, Permission permission) {
CodeSource codeSource = domain.getCodeSource();
if (codeSource == null) {
return false;
}
URL location = codeSource.getLocation();
if (location != null) {
//get the custom plugin policy rules and validate the permissions
Policy plugin = this.plugins.get(location.getFile());
if (plugin != null) {
return plugin.implies(domain, permission);
}
}
return defaultSystemPermissions().implies(permission);
}
private PermissionCollection defaultSystemPermissions() {
Permissions permissions = new Permissions();
permissions.add(new AllPermission()); // this will set the application default permissions, in there we enable all
return permissions;
}
}在上面的代码中,将验证权限 of 动态类,如果缺乏相应的权限,则在运行时将抛出:
java.security.AccessControlException: access denied ("java.io.FilePermission" "test.txt" "read")在那里还启用了默认应用程序的所有权限,也许应该在实际场景中更多地考虑它。
3.为您的SecurityManager动态策略安装setPolicy并安装它。
// load the dynamic classes
URL pluginClass = new File("./myplugin").toURI().toURL();
// read my plugin security policy
URIParameter myPolicyPath = new URIParameter(MyClass.class.getResource("/my.policy").toURI());
Policy policy = Policy.getInstance("JavaPolicy", myPolicyPath);
MyPolicy myPolicy = new MyPolicy(ImmutableMap.of(pluginClass.getPath(), policy));
Policy.setPolicy(myPolicy);
// install the security manager
System.setSecurityManager(new SecurityManager());4.完整的例子: TestClass:
public class TestClass {
public void foobar() throws IOException {
Path path = Paths.get("test.txt");
String lines = Files.readAllLines(path).stream().collect(Collectors.joining(","));
System.out.println(lines);
}
}跑步者:
public static void main(String[] args) throws Exception{
// create a new url class loader, this can be used to load a jar or classes directory
URL pluginClass = new File("./myplugin").toURI().toURL();
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{pluginClass}, MyClass.class.getClassLoader());
// load a dynamic TestClass class
Class loadedMyClass = urlClassLoader.loadClass("TestClass");
// read my plugin security policy
URIParameter myPolicyPath = new URIParameter(MyClass.class.getResource("/my.policy").toURI());
Policy policy = Policy.getInstance("JavaPolicy", myPolicyPath);
MyPolicy myPolicy = new MyPolicy(ImmutableMap.of(pluginClass.getPath(), policy));
Policy.setPolicy(myPolicy);
// install the security manager
System.setSecurityManager(new SecurityManager());
System.out.println("Loaded class: " + loadedMyClass.getName());
Object myClassObject = loadedMyClass.getConstructor().newInstance();
Method method = loadedMyClass.getMethod("foobar");
System.out.println("Invoked method: " + method.getName());
method.invoke(myClassObject);
}参考资料:
https://docs.oracle.com/javase/tutorial/essential/environment/security.html
发布于 2018-08-24 09:35:44
与其侵入您自己的解决方案,不如使用内置的SecurityManager来处理针对不同任务的各种不同权限。
https://stackoverflow.com/questions/52001421
复制相似问题