Отбросить привилегии процесса

12

У меня есть процесс, который запускается дэймоном, работающим от имени root, теперь я хочу «понизить» привилегии этого процесса до привилегий вашего обычного пользователя. Это возможно? Если да, то как?

PS: работает Unix на Mac

Саманта Катания
источник

Ответы:

5

Сам процесс должен вызвать setuid (2). Вам также следует изучить запуск его внутри chroot (8), если вы этого еще не сделали. Насколько я знаю, root не может изменить uid другого процесса.

Если причина, по которой вы используете его как root, заключается в том, чтобы связать порты, я бы предложил запустить его как обычный пользователь на более высоком порту и использовать ipfw (8) в OS X для перенаправления порта 80/443 / etc на более высокий порт:

http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx

многочлен
источник
Я установил setuid (uid) в моей программе, которая запускается от имени пользователя root, но мне нужно, чтобы он работал от имени обычного пользователя, и ничего не происходит, т.е. он продолжает работать от имени пользователя root
Samantha Catania,
Вам, вероятно, нужно поймать ошибки из этого (возможно, вы получаете EINVAL для UID). Его маловероятный setuid не работает на вашей машине, вы можете проверить, посмотрев, работает ли apache как _www. Документы для программистов: developer.apple.com/library/mac/#documentation/Darwin/Reference/…
полином
вы правы, выдает синтаксическую ошибку от uid, даже если это правильно. это правильный формат setuid (500)?
Саманта Катания
обнаружил проблему: я пытался запустить команду через system (), но я просто запустил команду, она работает и решил мою проблему; Спасибо за помощь
Саманта Катания
Нет. Это плохой совет: setuid()одного звонка совершенно недостаточно.
Николас Уилсон
13

sudo tcpdump -Z использует initgroups (3), setgid (2) и setuid (2) для удаления корневых привилегий своего собственного процесса.

# code taken from: 
# http://www.opensource.apple.com/source/tcpdump/tcpdump-32/tcpdump/tcpdump.c

/* Drop root privileges and chroot if necessary */
static void
droproot(const char *username, const char *chroot_dir)
{
...
            if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
               setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
                    fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
                        username, 
                        (unsigned long)pw->pw_uid,
                        (unsigned long)pw->pw_gid,
                        pcap_strerror(errno));
                    exit(1);
            }
...
}
phron
источник
2
Верный. initgroups, setgid, setuid(Наконец!) Именно право парадигмы на UNIX, и всегда должны быть соблюдены. Кроме того, ответственная функция «droproot» проверяет, что ее uid и gid действительно установлены, даже если все три основные функции вернули успех.
Николас Уилсон
3

Вы можете запускать команды как другие пользователи, используя su:

 su USERNAME -c COMMAND

Будет работать COMMANDс привилегиями USER.


Обратите внимание, что по умолчанию suдля запуска команды будет использоваться интерпретатор оболочки целевого пользователя. В отличие от этого, стандартным поведением sudoявляется обработка COMMANDотдельной программы, которая запускается в текущей среде. Конечно, это поведение по умолчанию может быть изменено с помощью различных переключателей и переменных среды.

rozcietrzewiacz
источник
Похоже su, не работает, если USERNAME не имеет определенной оболочки (или /bin/false), тогда как sudo работает.
Aif
1
@Aif Если пользователю не разрешено запускать интерактивные команды, поведение по умолчаниюsu будет отражать это. Тем не менее, всегда можно изменить это с помощью -sпереключателя. Обратите внимание, что цель suсостоит в том, чтобы имитировать поведение данного пользователя, на которое обычно влияет его / ее оболочка. В отличие от sudoэтого (по умолчанию) будет игнорировать настройки оболочки целевого пользователя.
rozcietrzewiacz
Нет, пожалуйста, не запускайте вещи, используя оболочку, просто чтобы сбросить привилегии. Это оставляет слишком много под контролем злоумышленника, читающего различные конфигурационные файлы, к которым вы не хотите прикасаться.
Николас Уилсон
2

Чтобы удалить привилегии, вам нужен не-root пользователь, чтобы перейти на. Тогда нужно просто переключиться на этого пользователя:

#define UNPRIV_UID  48
#define UNPRIV_GID  48

if (getuid() == 0) { // we are root
    // setting UID/GID requires root privileges, so if you don't set
    // the GID first, you won't be able to do it at all.
    if (setgid(UNPRIV_GID)!=0) die("Failed to set nonroot GID");
    if (setuid(UNPRIV_UID)!=0) die("Failed to set nonroot UID");
}

ASSERT(getuid() != 0); 

Обратите внимание, что это делается в самой программе , а не в скрипте-оболочке. Многие программы требуют привилегий суперпользователя для какой-то конкретной цели (например, для привязки к порту с небольшим номером), но после этого корень не требуется. Таким образом, эти программы будут запускаться с правами суперпользователя, но затем будут отбрасывать привилегии, когда они больше не нужны.

Если вам вообще не нужны привилегии root, просто не запускайте его как root. Например:

# Change this:
myprog -C /my/config/file

# To this:
sudo -u someuser myprog -C /my/config/file
# Or this
su someuser -c "myprog -C /my/config/file"
tylerl
источник
1
Обратите внимание, что это позволяет процессу восстановить привилегии, если он этого хочет! setuidФункция устанавливает только эффективный UID, а не реальный UID. Вы должны использовать, setreuidесли вы не хотите, чтобы процесс мог вернуть привилегии. (И приведенный выше код также не относится к дополнительным групповым привилегиям. Он подходит только для запуска кода с наибольшим доверием.)
Дэвид Шварц,
Код Дэвида Шварца был преднамеренно упрощен, чтобы показать используемый механизм.
Тайлер
Если вы собираетесь упростить безопасность критичных кода, вы должны сделать это очень ясно , что это то , что вы делаете. И вы должны говорить такие вещи, как «это просто вопрос», когда это не так.
Дэвид Шварц
2
@David На самом деле, setuid()устанавливает реальные и сохраненные идентификаторы пользователей; Вы можете думать о seteuid(). Не все системы имеют setreuid(), поэтому он не может быть использован везде. Точная семантика setuid()сложна, но если у вас есть euid 0, вы сможете отбросить все традиционные привилегии пользователя с помощью setuid(). Самым большим упущением в этом ответе является то, что initgroupsили setgroupsдолжно быть названо так же, как setgidи setuid, и что более тщательные утверждения должны быть сделаны в конце.
Николас Уилсон
0

Если вы выполняете другой исполняемый файл, то есть вы вызываете execveили другую execфункцию из семейства, возможно, косвенно через функцию, подобную systemили popen, и дочерний процесс должен запускаться без привилегий с самого начала, тогда самый простой способ - это получить Оболочка участвует, и звоните su. Вот краткий обзор того, как может выглядеть код в Perl, с указанием цитаты, необходимой для:

$shell_command = quotemeta($path_to_executable) . " --option";
$shell_command =~ s/'/'\\''/; # protect single quotes for the use as argument to su
$su_command = sprintf("su -c '%s' %s", $shell_command, quotemeta($user_name));
open(PIPE, "$su_command |") or die;

Если дочерний процесс должен запускаться с правами root, но позднее отбрасывать привилегии, см. Код в этом ответе , который иллюстрирует, как понизить привилегии в процессе.

Жиль "ТАК - прекрати быть злым"
источник