Привілеї процесу відкидання


12

У мене є процес, який починається від демона, що працює під керуванням root, тепер я хочу "знизити" привілеї цього процесу до тих, що мають ваш середній користувач. Чи можливо це? Якщо так, то як?

PS: Запуск Unix на mac

Відповіді:


5

Сам процес повинен викликати setuid (2). Ви також повинні дослідити запуск його в chroot (8), якщо ви ще цього не зробили. Наскільки я знаю, немає можливості кореня змінити uid іншого процесу.

Якщо причина, за якою ви запускаєте його як root, пов’язує порти, я б запропонував запустити його як звичайний користувач на більш високому порту та використовувати ipfw (8) в OS X для пересилання порту 80/443 / тощо на більш високий порт:

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


Я поставив setuid (uid) у своїй програмі, що працює як root, але мені це потрібно для запуску як звичайний користувач, і нічого не відбувається, тобто він продовжує працювати як root
Samantha Catania,

Вам, ймовірно, потрібно буде потім виправити помилки (можливо, ви отримуєте EINVAL для uid). Його навряд чи встановлено на вашій машині, ви можете перевірити, чи працює apache як _www. Документи програміста: developer.apple.com/library/mac/#documentation/Darwin/Reference/…
поліном

ви праві, це дає помилку синтаксису від uid, навіть якщо це правильно. це правильний параметр формату (500)?
Саманта Катанія

виявив проблему: я намагався запустити команду через system (), але я просто запустив команду, яка працює, і вирішила мою проблему; THX на допомогу
Саманта Катанія

Ні. Це не хороша порада: телефонувати 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);
            }
...
}

2
Правильно. initgroups, setgid, setuid(Нарешті!) Саме право парадигми на UNIX, і завжди повинні бути дотримані. Крім того, відповідальна функція "droproot" перевіряє, чи справді встановлені його uid та gid, навіть якщо всі три основні функції повернули успіх.
Ніколас Вілсон

3

Ви можете запускати команди як інші користувачі, використовуючи su:

 su USERNAME -c COMMAND

Буде працювати COMMANDз пільгами, скинутими на USER.


Зауважте, що за замовчуванням suдля виконання команди буде використовувати інтерпретатор оболонки цільового користувача. На противагу цьому, поведінка за замовчуванням sudo- це трактувати COMMANDяк окрему програму, тобто керувати поточним середовищем. Звичайно, ці поведінки за замовчуванням можуть бути змінені різними перемикачами та змінними середовища.


Схоже, suце не працює, якщо USERNAME не має оболонки (або /bin/false), тоді як sudo працює.
Ейф

1
@Aif Якщо користувачеві заборонено виконувати інтерактивні команди, то поведінка за замовчуваннямsu відобразить це. Однак завжди можна перекрити це за допомогою -sперемикача. Зауважте, що мета su- імітувати поведінку даного користувача - на що зазвичай впливає його / її оболонка. Навпаки, sudoбуде (за замовчуванням) ігнорувати налаштування оболонки цільового користувача.
rozcietrzewiacz

Ні, будь ласка, не запускайте речі, використовуючи оболонку, просто скидаючи привілеї. Це занадто сильно залишає контроль над зловмисником, читаючи різні конфігураційні файли, до яких ви не хочете торкатися.
Ніколас Вілсон

2

Щоб скасувати привілеї, вам потрібно некористувальницького користувача, на який потрібно перейти. Тоді лише питання про перехід до цього користувача:

#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 не потребує цього. Тож ці програми запускаються як root, але потім скасовують привілеї, коли вони більше не потрібні.

Якщо вам зовсім не потрібні привілеї 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"

1
Зауважте, що це дозволяє процесу відновити привілеї, якщо він цього хоче! setuidФункція встановлює тільки ефективний UID, а не справжній UID. Вам слід скористатися, setreuidякщо ви не хочете, щоб процес міг повернути привілеї. (І вищевказаний код не стосується додаткових привілеїв для групи. Він підходить лише для запуску коду, який є більш надійним.)
David Schwartz

@David Schwartz код був навмисно спрощений, щоб показати застосований механізм.
tylerl

Якщо ви збираєтеся спростити безпеку критичних коду, ви повинні зробити це дуже ясно , що це те , що ви робите. І вам слід сказати такі речі, як "це просто питання", коли це не так.
Девід Шварц

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, але пізніше скасувати привілеї, дивіться код у цій відповіді , який ілюструє, як зменшити привілеї в процесі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.