Чи може програма сказати, що вона працює під sudo?


27

У мене є програма, яка повинна поводитись інакше, якщо вона запускається під "судо". Чи є спосіб це дізнатись, чи був він запускається під судо?

Оновлення: хтось запитав, чому я хочу це зробити? У цьому випадку на Mac, що використовує MacPorts, є вихід, який підказує вам вирізати та вставити певну команду. Якщо команда MacPorts виконувалася із "sudo", вона повинна включати sudo у зразок команди:

$ sudo port selfupdate 
--->  Updating MacPorts base sources using rsync
MacPorts base version 2.2.1 installed,
MacPorts base version 2.2.1 downloaded.
--->  Updating the ports tree
--->  MacPorts base is already the latest version

The ports tree has been updated. To upgrade your installed ports, you should run
  port upgrade outdated

^^^^^^^^^ it would be really sweet if it output "sudo port upgrade outdated" instead.  It would be even better if it just did it for you :-)

Мені цікаво: чи можете ви пояснити, як має поводитися по-різному?
sciurus

1
@sciurus зазвичай звичайний випадок використання знаходиться в сценарії встановлення, який вимагає кореневих привілеїв; якщо у вас їх немає, просто помирайте негайно.
Нік Т


Я смутно пам'ятаю, як якась команда усвідомлювала, що вона працює як root або ні ... Я думаю, що відповідь "так"
Рольф

Відповіді:


48

Так, під час запуску програми під sudo встановлено 4 змінні середовища:

$ sudo env |grep SUDO
SUDO_COMMAND=/usr/bin/env
SUDO_USER=tal
SUDO_UID=501
SUDO_GID=20

Зауважте, що їх можна підробити, просто встановивши їх. Не вірте їм нічого критичного.

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

#!/bin/bash

echo 'Thank you for running me.'

if [[ $(id -u) == 0 ]]; then
  if [[ -z "$SUDO_COMMAND" ]]; then
    echo 'Please now run: next_command'
  else
    echo 'Please now run: sudo next_command'
  fi
else  echo 'Error: Sadly you need to run me as root.'
  exit 1
fi

Зауважте, що він тестує лише змінну SUDO_ *, якщо спочатку може довести, що вона працює як root. Навіть тоді він використовує його лише для зміни корисного тексту.


2
Що б я використав для "нічого критичного?"
Кевін - Відновіть Моніку

3
@Kevin, якщо хтось обертається своїм оточенням, щоб підробити те, що вони мають підвищені привілеї, то вони, сподіваючись, знають, що вони роблять, і приймуть наслідки.
Нік Т

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

Це цілком прийнятна відповідь на поставлене питання. Попередження повинно бути для людей, які можуть спробувати запобігти використанню судо, а не просто виявити його. Профілактику слід проводити за допомогою псевдонімів команд sudo, щоб обмежити, які команди може виконувати користувач.
dwurf

11

Це не відповідає на питання безпосередньо, але я не думаю, що тут задають правильне питання. Мені здається, що запитувач хоче, щоб програма, яка діятиме інакше, мабуть, якщо вона має певні дозволи чи ні, однак я б стверджував, що перевірка судо - це не спосіб це зробити. По-перше, багато систем можуть не реалізувати "sudo", це ні в якому разі не потрібно для Linux або багатьох Unixes.

Наприклад, користувач може вже увійти до системи як root, що робить sudo безглуздим, або, можливо, у системі є некористувальні користувачі, які все ще мають можливості виконувати адміністративне завдання, яке, можливо, захоче виконати програма. Нарешті, можливо, система взагалі не має root або sudo, а натомість використовує обов'язкову систему управління доступом з різними можливостями, і не може спіймати всіх суперпользователей, щоб вступити в судо. Або користувач може бути призначений для суду, але в обліковий запис, який не має дозволів, ніж їх власний обліковий запис, з міркувань безпеки (я часто запускаю недовірений код з тимчасовим непривілейованим користувачем, який може писати лише на ramdisks для того, щоб скасувати, а не підвищувати мої дозволи ). Загалом погана ідея припускати таку модель дозволів, як sudo або існування root, або припускати, що користувач sudoed має певні привілеї.

Якщо ви хочете дізнатися, чи є у вас дозволи на виконання операції, найкращий спосіб - це просто спробувати виконати це, тоді перевірте помилку errno на наявність дозволів, якщо вона не працює, або якщо це багатоетапна операція, яка повинна або всі вийти з ладу, або все вдасться Ви можете перевірити, чи буде діяти така функція, як функція доступу POSIX (остерігайтеся можливих умов гонки тут, якщо дозволи активно змінюються)

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

Нарешті, якщо ви дійсно хочете дізнатися, чи має користувач доступ до кореня (все-таки погана ідея, але менш специфічна для реалізації), ви можете скористатися getuid, щоб перевірити наявність uid 0 та, таким чином, root.


7

Є два механізми, які можна використовувати.

  • Перевірка змінних оточуючих середовищ може бути підробленою будь-яким способом, але це найлегше зробити. growisofsне любить працювати під SUDO, тому я скидаю змінні SUDO в скриптах, де я його використовую. Його можна підробити і в інший спосіб. (Змінна SUDO також переноситься в середовище для сценаріїв, що виконуються під командами at і batch.)
  • Ще один спосіб дізнатися, чи працюєте ви під судо - це перейти до списку процесів від вашого батьківського процесу, шукаючи судо. Важко було б приховати, що ти так бігав під судо, але це складніше. Ще можна підробити, що ти працюєш під судо.

Частіше перевіряється, чи працює ви як відповідний користувач. Для цього idможна використовувати команду. Сценарій TomOnTime використовує idкоманду, щоб визначити, чи sudoможе знадобитися наступна команда.


1
> Важко було б приховати, що ти таким чином бігав під судо. Чи не могли ти просто перейменувати sudoбінарне на щось інше? Або назвіть якийсь інший виконуваний файл, sudoщоб підробити протилежне? Не те, щоб я дійсно очікував, що хтось розумний це зробити ...
Боб

@Bob Вам знадобиться rootдоступ, щоб перейменувати sudoвиконуваний файл. Звичайний користувач не міг би цього зробити. Я зауважив, що ви можете підробити, що ваш працює під sudo. Перейменування існуючої програми спрацювало б. Код, необхідний для спеціальної підробленої sudoпрограми, є тривіальним.
BillThor

ви можете просто завантажити звідкись бінарний файл судо і дати йому правильні дозволи ...
Jens Timmerman

@JensTimmerman Вам потрібен кореневий доступ, щоб надати йому правильні дозволи. Якщо ви можете просто перейменувати його або жорстко пов’язати його. Не потрібно його завантажувати. Якщо ви встановите його SUID на цільовий ідентифікатор користувача (якщо він буде працювати таким чином), вам доведеться вже поставити під загрозу ідентифікатор цільового користувача.
BillThor

ага, так, вона відмовляється працювати без встановлення, моє погано ...
Jens Timmerman

2

Ви можете порівняти ефективний і реальний ідентифікатор користувача.

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


2
Ні, sudoвстановлює і ефективний, і реальний ідентифікатор. На відміну від самогубства, чого немає. Ось банальна програма C, яку ви можете використати для тестування (вибачте, коментар видалить нові рядки, вам доведеться додати їх назад):#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { printf("real = %i, effective = %i\n", getuid(), geteuid()); return 0; }
derobert

... або, альтернативно,perl -E 'say $<, "\n", $>'
дероберт

2

Ви можете перевірити ефективну змінну UID (EUID) таким чином:

if [[ $EUID -eq 0 ]]; then
    echo "running as root"
else
    echo "not running as root"
fi

Це не дає відповіді на запитання. Код дає такий же вихід при запуску як root, як і при запуску як sudo.
Стівен C

@StephenC - я думаю, що для цілей ОП різниці немає. Їх мета IMHO - виявити виконання або виконання sudo з автентичної кореневої оболонки без розрізнення.
Еліран Малька

1
Я думаю, ти можеш мати рацію. Я прийшов сюди, тому що не зрозумів, чому sudo echo $USERдрукує непривілейоване ім’я користувача (змінна замінена ДО СУДО). Я фактично використовував ваш код у своєму сценарії. Дякую!
Стівен C

привітатись :)
Еліран Малька

-1

Ви можете торкнутися файлу в ньому, /rootа потім if -eйого. І якщо -e вірно, rm(перевірка коду помилки), то ваш тест працює наступного разу.

Перевірка коду помилки (або повернення коду) після rm не дозволяє комусь зручно використовувати повноваження sudo, щоб створити файл для відтворення на вас шахрайства.


4
Ця відповідь перевіряє, чи має процес дозвіл на запис /root(що не обов'язково збігається з UID 0), але не перевіряє, чи отримав він ці дозволи, використовуючи sudo.
Ladadadada

Так, "тисяча способів скинути кішку"; Коли я писав відповідь, я придумав ще 4 або 5 речей, тому я завершив її.
Кріс К

-2

Я виявив, що це добре працює для цього

[ $(cat /proc/$PPID/loginuid) -ne 0 ] && [ "$USER" == "root" ]

Це не працює, коли я пробую його на FreeBSD, Centos7 або MacOS X. Я думаю, ви маєте на увазі "/ proc" замість "/ etc". Але навіть із цією зміною він не працює ні на одній із цих трьох. "US USER" скидається sudo. Ви мали на увазі $ SUDO_USER? Також ви мали на увазі "[[" замість "["?
TomOnTime

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