Как обезопасить Java-приложение при динамической загрузке классов? - PullRequest
0 голосов
/ 24 августа 2018

У меня есть приложение Java / Scala, которое выполняет дисковый ввод-вывод, а также динамически загружает классы, отправленные пользователями.Динамические классы работают под своими собственными ClassLoaders.

Какие проблемы безопасности следует учитывать при загрузке этих классов, чтобы гарантировать, что у них нет разрешения на удаление файлов на диске или выполнение каких-либо вредоносных действий, и они просто выполняют операции в памяти?

Что я сделал до сих пор

  • Проверки регулярных выражений для удаления java.io.*, java.nio.*, java.lang.reflect & java.lang.Runtime.* связанных импортов.Я пытаюсь выяснить, можно ли удалить этот импорт из пути к классам напрямую вместо выполнения регулярного выражения.
  • Время ожидания устанавливается для каждого выполнения экземпляра динамически загруженного класса.
  • Письменная проверка загрузки 1000 склассов, динамически загружаемых для проверки проблем PermGen, и не было утечек памяти.

Другой вариант - запускать их в своем собственном процессе JVM и устанавливать разрешения уровня файловой системы (Linux) для каждого процесса, но это не очень хорошо подходит для моего решения, потому что мне нужно, чтобы они делились потокобезопаснымиобъекты в памяти.

Может кто-нибудь предложить, что еще следует учитывать, и если я на правильном пути?

Ответы [ 2 ]

0 голосов
/ 25 августа 2018

Как сказал @Kayaman, вы должны попытаться использовать SecurityManager для обработки этих динамических классов разрешений , есть минимальный пример, чтобы продемонстрировать это, может быть, это полезно для вас.

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;
    }
}

В приведенном выше коде будет проверено разрешение из динамических классов , если отсутствие соответствующего разрешения , во время выполнения он выдаст:

java.security.AccessControlException: access denied ("java.io.FilePermission" "test.txt" "read")

также там включено все разрешения для приложения по умолчанию , возможно, следует рассмотреть больше об этом в реальном сценарии.

3. setPolicy и установите SecurityManager для ваших динамических политик .

        // 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);
    }
}

Runner:

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

0 голосов
/ 24 августа 2018

Вместо взлома ваших собственных решений, используйте встроенный SecurityManager для обработки всех видов различных разрешений для различных задач.

...