Як запобігти користувачам sudo виконувати певні команди?


29

У мене дуже чутлива настройка мережі, і я дуже не хочу зіпсувати це. Моя мережа складається з безлічі користувачів, які мають привілей на sudo.

Я хочу перешкодити їм бігати

service NetworkManager restart
service network restart

команди.

Чи є якийсь спосіб я досягти цього?


Який розподіл ви використовуєте? Назви служб конкретні для дистрибутиву, і я не знаю жодного дистрибутива, який використовує імена, які у вас є. Ви маєте на увазі networkingі network-manager? Крім того, чому ваші користувачі мають sudoдоступ? Вони не повинні, якщо ви не хочете, щоб вони мали повні права root.
тердон

@terdon Я це вирішив. Дякую. Я не можу опублікувати це як відповідь, тому що я новий користувач
shekhar

Так, можете, будь ласка. Я також хотів би дізнатися відповідь, яку ви знайшли.
тердон

@terdon впевнений, але його висловлювання мені потрібно чекати 8 годин, щоб опублікувати власну відповідь, тому що я не маю навіть 10 репутації
shekhar

1
Ах, так, вибачте, справді потрібно чекати. Я щойно підтримав пропозицію, у вас зараз є представник :)
terdon

Відповіді:


47

Використання CmndAlias ALLніколи не буде безпечним

Є 1000 способів бігати, service network restartне роблячи sudo service network restart. Ось приклад того, що може спробувати неслухняний користувач:

$ echo "service network restart" > /tmp/hax
$ chmod a+x /tmp/hax
$ sudo /tmp/hax

Якщо ви надасте користувачам ALLпсевдонім команди, а потім спробуєте створити чорний список, вони завжди зможуть знайти шлях до нього. Чорний список bash, і вони будуть використовувати python. Чорний список пітона, і вони використовуватимуть Perl. Чорний список Perl, і вони використовуватимуть PHP. Ніхто цього не хоче!

Якщо ви дійсно не хочете , щоб хто - то що - то зробити, ви повинні робити , як каже Томас, і створити білий список речей , які вони мають право робити.


Налаштування білого списку за винятком

Приклад невеликого білого списку з виключенням можна знайти внизу man sudoers:

 pete           HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root

The user pete is allowed to change anyone's password except for root on the HPPA
machines.  Note that this assumes passwd(1) does not take multiple user names
on the command line.

(Насправді цей приклад із сторінки сторінки небезпечний і може бути використаний для зміни пароля root! Див. Коментарі нижче про те, як.)

Ми можемо спробувати пристосувати , що ваш випадок, щоб запропонувати все serviceкоманди в групі співробітників, але виключають ті service networkкоманди , які стосуються вас:

%staff ALL =   /usr/sbin/service *,                            \
             ! /usr/sbin/service *network*,                    \
             ! /usr/sbin/service *NetworkManager*

ALLцій позиції посилається на Host_Alias, а не на Cmnd_Alias ​​- не так?)

Користувач не зможе запустити sudo bashабо sudo teeабо sudo wgetабо sudo /path/to/malicious_script. Якщо ви обережні, ви можете додати до списку більше команд адміністратора для своїх користувачів. Просто будьте конкретні!

Примітка. *До цього слова я додав слово networkвище, лише на випадок, якщо в serviceмайбутньому до інструменту буде додано нешкідливий прапор . Уявімо, що --verboseпрапор буде додано в майбутньому, і користувачі зможуть запустити наступне:

$ sudo service --verbose network restart

Тому нам потрібно *споживати будь-які прапори перед назвою служби. Один недолік полягає в тому, що це може заблокувати інші сервіси, які ви насправді не заважаєте користувачам, наприклад, послугу, яка викликається safe-networkабо network-monitorтакож буде відхилена.


Дозволити користувачам редагувати файл за допомогою групових дозволів

Нижче ви можете знайти різні спроби, rnanoзавдяки яким sudoкористувачі можуть редагувати файл або файли. Але насправді вони складніші та небезпечніші, ніж повинні бути.

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

### Give steve the ability to edit his nginx config:
$ chgrp steve /etc/nginx/sites-available/steves_dodgy_project
$ chmod g+rw /etc/nginx/sites-available/steves_dodgy_project

### Let all members of the staff group edit the group_website config:
$ chgrp staff /etc/nginx/sites-available/group_website
$ chmod g+rw /etc/nginx/sites-available/group_website

Якщо вам потрібен більш тонкий контроль (наприклад, доступ лише для трьох користувачів, але не всіх співробітників), ви можете створити нову групу за допомогою addgroupкоманди та додати до неї лише декілька користувачів.


Дозвольте користувачам редагувати файл наскрізь sudo

Залишок цієї відповіді став розслідуванням того, наскільки легко залишати дірки у своїй sudoконфігурації, намагаючись запропонувати своїм користувачам гнучкість. Я б не рекомендував робити щось із наступного!

Якщо ви хочете надати своїм користувачам доступ для редагування певного файлу, ви можете спробувати скористатися rnano:

%staff ALL = /bin/rnano /etc/nginx/sites-available/host

rnanoдозволить лише їм редагувати вказаний файл. Це важливо, щоб зловмисний користувач не міг редагувати іншу послугу для /etc/init.d/urandomзапуску (наприклад ) та додати до неї рядок, який би запускався service network restart.

На жаль, я не знайшов способу обмежитись rvimдостатньо (користувач все ще може відкрити будь-який файл, використовуючи :e), тому ми застрягли nano.

На жаль, дозволити користувачам редагувати кілька файлів набагато складніше ...


Дозвольте користувачам редагувати кілька файлів (набагато складніше, ніж це повинно бути)

1. Небезпечні підходи

Будьте обережні з подвійних карт! Якщо ви пропонуєте занадто велику гнучкість (або будь-яку гнучкість), її можна використовувати:

%staff ALL = /bin/rnano /etc/nginx/sites-available/*                # UNSAFE!

У цьому випадку зловмисний користувач зможе відредагувати будь-який інший сценарій початкової служби та запустити його:

$ sudo rnano /etc/nginx/sites-available/../../../any/file/on/the/system

(Судо насправді запобігає .і ..розширює команду, але, на жаль, не на аргументах.)

Я сподівався, що щось подібне може спрацювати, але воно все ще є небезпечним:

%staff ALL = /bin/rnano /etc/nginx/sites-available/[A-Za-z0-9_-]*   # UNSAFE!

Оскільки на sudoсьогоднішній день пропонуються лише глобальні шаблони, це *буде відповідати чому завгодно - це не регулярне вираження!

(Редагувати: я враховував, чи можете ви уникнути вищезазначеного у вашій ситуації, оскільки під ним немає підпапок sites-available. Ми вимагали, щоб одна папка збігалася за папкою, і вона /..повинна вийти з ладу після імені файлу. Однак це не працездатне рішення, оскільки rnanoприймає декілька аргументів. І взагалі це все-таки було б небезпечно для папки, в якій були папки!)

Навіть якщо у нас немає підпапок, і ми виключаємо будь-які рядки, що містять /../, правило, яке пропонує *глобус, все одно може бути використане, оскільки воно rnanoприймає декілька аргументів (проїжджаючи через них <C-X>, і простір з радістю приймається *глобусом.

$ rnano /etc/nginx/sites-available/legal_file /then/any/file/on/the/system

2. Натискання на конверт (також в кінцевому рахунку небезпечно)

Що робити, якщо ми відхиляємо будь-які рядки, що містять пробіли, або намагаємось досягти /..? Тоді остаточним можливим рішенням може бути таке:

# I tried hard to make this safe, but in the end I failed again.
# Please don't use this unless you are really smart or really stupid.

%staff ALL =   /bin/rnano /etc/nginx/sites-available/*,    \
             ! /bin/rnano */..*,                           \
             ! /bin/rnano /etc/nginx/sites-available/,     \
             ! /bin/rnano */.,                             \
             ! /bin/rnano * *

# CONCLUSION: It is still NOT SAFE if there are any subfolders, due to
# the bug in rnano described below.

Ми приймаємо що - небудь «під» папку , але ми також відкидаємо будь-який виклик , rnanoякщо /..або /.або пропускаються, або якщо папка призначена безпосередньо. (Технічно /.виключення робить це /..виключення зайвим, але я залишив обох для ясності.)

Я знайшов папку, і /.виключення були потрібні, оскільки в іншому випадку користувач міг націлити на папку. Тепер ви можете подумати, rnanoщо заблокували, якби вказали на папку, але ви помиляєтесь. Насправді моя версія (2.2.6-1ubuntu1) починається з легкого попередження та порожнього файлу, після чого <C-X>просить мене ввести будь-яке ім'я файлу, до якого я хотів би зберегти, відкриваючи новий вектор атаки! Принаймні, він відмовився перезаписати існуючий файл (в одному тесті, який я зробив). У будь-якому випадку, оскільки немає можливості перетворити в папки в чорний список судо, ми повинні зробити висновок, що такий підхід знову небезпечний. Вибачте користувачів!

Це відкриття змусило мене сумніватися у ґрунтовності nano"обмеженого" режиму. Кажуть, ланцюжок настільки ж міцний, як і його найслабша ланка. Я починаю відчувати поєднання sudoчорної магії чорного списку і, rnanoможливо, не є більш безпечним, ніж ланцюжок ромашок.

3. Безпечні, але обмежені підходи

Глобуси дуже обмежені - вони не дозволяють нам кілька разів порівнювати клас персонажів. Ви можете запропонувати кілька редагувань файлів, якщо всі ваші імена файлів мають однакову довжину (у цьому випадку hostслідує одна цифра):

%staff ALL = /bin/rnano /etc/nginx/sites-available/host[0-9]       # SAFE

Але якщо ви хочете надати користувачеві доступ для редагування різних файлів, можливо, вам потрібно буде чітко вказати кожен файл:

%staff ALL = /bin/rnano /etc/nginx/sites-available/hothost    \
             /bin/rnano /etc/nginx/sites-available/coldhost   \    # SAFE
             /bin/rnano /etc/nginx/sites-available/wethost    \
             /bin/rnano /etc/nginx/sites-available/steves_dodgy_project

Не спокушайтесь використовувати в*будь-якій точці. Дивіться розділи 1. та 2. вище для чого! Пам’ятайте: одна невелика прокладка може поставити під загрозу весь рахунок суперпользователя та всю систему.

4. Напишіть свою перевірку аргументів (безпека тепер ваша відповідальність)

Я сподіваюся, що вони нададуть підтримку regexp sudoв майбутньому; При правильному використанні це може вирішити багато проблем. Але нам може знадобитися також можливість перевірити властивості аргументів (дозволити лише файли, лише папки або лише певні прапорці).

Але є одна альтернатива - створити гнучкість у судо. Передайте долар:

%staff ALL = /root/bin/staffedit *

Потім напишіть власний staffeditскрипт або виконуваний файл, щоб перевірити, чи аргументи, передані користувачем, є законними, і виконайте їх запит лише у разі їх наявності.


5
Ця відповідь зайняла багато часу, але, нарешті, я думаю, я розумію, як працює судо. У минулому я відмовлявся від різних випадків, вважаючи, що ALL=(ALL:ALL) ALLзанадто бракує семантики, але завжди десь припускав, що це буде гідна перевірка аргументів ... Я помилявся. Це дійсно дуже обмежено. Навіть PASSWD корінь виняток пропонується в людино-сторінці може бути зламано з допомогою простого аргументу командного рядка, sudo passwd -q root. Добре автори судо перелічують [деякі альтернативи] (sudo.ws/sudo/other.html) на своєму веб-сайті. Я сподіваюся, що вони нададуть підтримку regexp в майбутньому.
joeytwiddle

Ви спеціально використовуєте rnanoтут свій опис, оскільки це версія нано, якій не вистачає функції "зберегти як"? Я не знайомий з програмою.
Шадур

Так. Якщо ми дбаємо про безпеку, редактор повинен тільки відредагувати один файл , вказаний, і не повинен бути в змозі відкрити оболонку. Для інформації, $ man nanoтоді/-R<Enter>
joeytwiddle

Виправлення: Для того, щоб зламати приклад Пітом, то -qповинні прийти потім: sudo passwd root -q. Приклад піта може бути посилений шляхом виключення *root*.
joeytwiddle

Подумайте sudoeditпро безпечне включення модифікації файлів за допомогою sudo.
Тотор

5

Спочатку відкрийте файл sudoers за допомогою sudo visudo. Додавання user ALL=!/usr/sbin/serviceбуде, IIRC, забороняє serviceкоманду для користувача user.

Джерела: http://nixcraft.com/showthread.php/15132-Sudo-Exclude-Commands-And-Disable-sudo-su-Bash-Shell


Це також перестане працювати з іншими службами, і я цього не хочу. Дякую за відповідь. :)
шекар

в той час як ваша відповідь не допомогла мені точно, але вона допомогла розробити рішення спасибі. але ти знаєш, чи дати тобі резюме або опублікувати мою робочу відповідь, я не маю достатньо репутації. Я обов'язково подякую, як тільки я стану. Дякую.
shekhar

2
Так, але все ж, як заявили інші, ви повинні бути дуже обережними з цим. Існує багато способів отримати доступ. Будь-яка команда, яка могла б породити оболонку тощо. Його простіше зрозуміти, які команди їм дійсно потрібні, і дозволити їх, а не намагатися виключити всі «заборонені».
Бонсі Скотт

3
Білі списки неможливі у багатьох сценаріях. Справжня мета може не полягати в тому, щоб запобігти їм щось робити, а навпаки, не давати їм зробити щось погане помилково, не обмежуючи їх інакше. Чорні списки в цих випадках хороші. Ви вносите в чорний список способи, яким розумний користувач вирішить завдання. Але чорний список через sudo може виявитися недостатнім - люди можуть і вживати "sudo bash". Одним із підходів буде обговорення команди «сервіс», а у випадках, коли ви не хочете, щоб вони користувалися, повідомляйте їх. Але ви ніколи не будете перелічувати всі добрі дії у білому списку, ані всі погані у чорному списку.
Боб Кернс

1
Я згоден з тобою, Боб. Щоб дозволити гнучкість, не допускаючи повного доступу, вам часто буде потрібно прокручувати власне рішення, як помічник сценарію, а білий список лише цього сценарію. Білі списки судо можуть робити все, що вам потрібно, але часто вони будуть або занадто обмеженими, або занадто простими в експлуатації.
joeytwiddle

5

Я знайшов рішення.

Я відкрив термінал і перейшов на root користувача, після su -чого набрав visudoредагування.

то наприкінці я написав рядки на кшталт

user ALL=!/etc/init.d/NetworkManager restart
user ALL=!/etc/init.d/network restart

Тоді я зберегти & закрити і перезапустити теж.

Тепер, якщо я набираю як service network restartабо service NetworkManager restartтоді, це не дозволяє мені і видає помилку

Sorry user is not allowed to execute '/sbin/service NetowkrManager restart' as root on localhost.localdomain

і аналогічно для service network restartкоманди також.


12
Це підійде для недосвідчених і недоброзичливих користувачів, але легко обійти обмеження судо (наприклад, sudo cp -p /etc/init.d/network /etc/init.d/network-not-in-sudoі тоді sudo /etc/init.d/network-not-in-sudo restart). Ось чому набагато безпечніше створювати включення замість виключень у файлі sudoers, наприклад, вказати, з якими службами їм дозволено взаємодіяти.
Томас

Все, що робить "перезапуск сервісної мережі", ви можете робити з іншими командами, такими, як у мережевому сценарії init.d. Я навіть не намагатимусь тут їх перелічити. Але якщо ви хочете, наприклад, фактично запобігти змінам стану інтерфейсу, то, здається, політика SELinux - це шлях. Це складна тема, але коли білий список є занадто обмежуючим або обтяжливим, а чорний список є неадекватним, це, мабуть, найкращий варіант. Він реалізований в ядрі і дозволяє обмежити доступ до мережевих інтерфейсів (та інших ресурсів) навіть для sudo'd користувачів.
Боб Кернс

Якщо це можливо з SELinux, тоді було б приємніше. @BobKerns Дякую Я спробую таким чином.
шекхар

3

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

joe@box:~$ sudo bash root@box:~# service network restart

Або інша забавна команда, яку вони можуть використовувати, щоб обійти ваші обмеження у файлі sudoers:

sudo visudo

Якщо коротко розповісти, якщо ви можете судо, і це не обмежується виконанням певних команд, ви можете робити майже все, що завгодно. Навіть якщо ви обмежите їх певним набором команд, вам доведеться переконатися, що користувач не може скопіювати якусь іншу команду, яку він хотів би запустити на те саме ім’я, як та, яку вони мали дозвіл на запуск ( наприклад, замінивши команду про те, що вони мають дозвіл на запуск.)


Так. Слід уникати команд, які можуть породжувати оболонку зсередини.
Бонсі Скотт

1
Проблема полягає в тому, що це не команди, які ви хочете захистити, а стан об'єктів ядра, таких як таблиці маршрутизації, інтерфейси тощо - незалежно від того, яка команда (або системний виклик) використовується. І ви хочете захистити його від деяких, але не всіх кореневих користувачів. SELinux розроблений навколо такого сценарію. Але спершу я б почав з огляду того, чому всі ці користувачі мають доступ до судо. Якщо їм потрібно виконати лише декілька конкретних речей, операції з білого списку на судорах можуть бути всім, що вам потрібно.
Боб Кернс

2

Використовуйте firejail, щоб обмежити користувачів пісочницями.

https://github.com/netblue30/firejail/

Встановіть firejail як оболонку замість bash в / etc / passwd, для кожного користувача, якого ви хочете обмежити. Він дуже простий у використанні та має гарну документацію.

Приклад:

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