JNI + setuid Вопрос

У меня есть веб-приложение, которое работает как пользователь www. Однако в какой-то момент ему нужно прочитать файл из файловой системы Linux от имени пользователей Алисы и Боба.

Один из способов сделать это — запустить оболочку (Runtime.exec()) и вызвать исполняемый файл C setuid для изменения идентификатора пользователя и чтения файла.

Есть ли способ добиться этого с помощью JNI (веб-приложение должно работать как www, а не как root)? Я попытался написать программу Java JNI, которая вызывает собственные методы в Linux (я сделал эти собственные методы принадлежащими root и установил биты setuid). Но если я не запускаю программу Java от имени пользователя root, она не позволяет мне переключать идентификаторы пользователей. Есть ли что-то, чего мне не хватает? Есть ли способ добиться этого?

Спасибо!


person Paula    schedule 12.05.2011    source источник


Ответы (2)


Нет. setuid и setgid можно использовать только в двух случаях (в обычном Linux):

  1. Процесс является корневым.
  2. Процесс был запущен из файла с битами setuid или setgid в его режимах.

В первом случае процесс может вызвать эти функции волей-неволей, чтобы принять любую идентичность. В последнем случае процесс может только переключаться между uid/gid родителя и uid/gid файла, из которого он был запущен.

То есть, если setuid, он может принять uid файла, если setgid — gid.

Поскольку вы работаете с java, исполняемая программа сама по себе является java, и вы не хотите, чтобы это было setuid или setgid, если только вы не хотите создать колоссальную угрозу безопасности.

Вы можете написать программу на C или C++, которая запускает JVM через интерфейс вызова JNI, и установить для этой программы значение setuid или setgid, а затем вызываемый там код JNI может выполнять соответствующие вызовы для переключения.

person bmargulies    schedule 16.05.2011

Да, это возможно. Вы можете увидеть пример здесь:

https://github.com/kebernet/pretty/blob/master/src/main/java/com/reachcall/util/SetUID.java

Вот пример кода:

CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);

   public static int setuid(int uid) {
        if (Platform.isWindows()) {
            return OK;
        }

        return CLibrary.INSTANCE.setuid(uid);
    }

ответ bmargulies неверен (или не совсем верен). Процесс без полномочий root в UNIX может устанавливать uid или gid, если у него есть соответствующие возможности:

http://man7.org/linux/man-pages/man7/capabilities.7.html

CAP_SETUID

  • Выполнять произвольные манипуляции с UID процессов (setuid(2), setreuid(2), setresuid(2), setfsuid(2));

Поскольку с точки зрения ОС ваша программа работает как процесс «java», эта возможность setguid должна быть включена для самого исполняемого файла java:

$ sudo setcap cap_setuid,cap_setgid+ep /usr/java/latest/bin/java

Также обратите внимание, что файловая система, в которой находится исполняемый файл Java, не монтируется с опцией nosuid.

Вернуться к исходному вопросу

веб-приложение должно работать как www, а не root

Обычно не рекомендуется позволять веб-службе иметь функцию setuid. Лучше добавить uid в сценарий-оболочку, который запускает ваше веб-приложение.

person Tagar    schedule 27.06.2017