Может ли программа сказать, что она запускается под sudo?

27

У меня есть программа, которая должна вести себя по-другому, если она запускается под "sudo". Есть ли способ узнать, запускался ли он под sudo?

Обновление: кто-то спросил, зачем мне это делать. В этом случае на 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 :-)
TomOnTime
источник
Мне любопытно: можете ли вы объяснить, как он должен вести себя по-другому?
Sciurus
1
@sciurus обычно используется в сценарии установки, который требует привилегий root; если их нет, просто умри немедленно.
Ник Т
3
Это звучит как meta.stackexchange.com/questions/66377/what-is-the-xy-problem/… . Что вы действительно хотите сделать?
Дженни Ди говорит восстановить Монику
Я смутно помню, как какая-то команда знала, что она запускается от имени пользователя root или нет ... Я думаю, что ответ "да"
Рольф

Ответы:

48

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

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

Обратите внимание, что их можно подделать, просто установив их. Не доверяй им ни за что критическое.

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

#!/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. Даже тогда это только использует это, чтобы изменить некоторый полезный текст.

TomOnTime
источник
2
Что бы я использовал для «чего-нибудь критического»?
Кевин - Восстановить Монику
3
@Kevin, если кто-то обманывает свою среду, чтобы имитировать существование с повышенными привилегиями, то он надеется, что знает, что делает, и примет последствия.
Ник Т
Плохо, потому что любой ответ, который должен быть квалифицирован как «не доверяй им ни за что критическое», - это вовсе не ответ, а уродливый взлом.
Стивен С.
Это вполне приемлемый ответ на заданный вопрос. Предупреждение должно быть там для людей, которые могут попытаться предотвратить использование sudo, а не просто обнаружить его. Предотвращение должно быть сделано с использованием псевдонимов команд sudo, чтобы ограничить то, какие команды может выполнять пользователь.
dwurf
11

Это не дает прямого ответа на вопрос, но я не думаю, что здесь задают правильный вопрос. Мне кажется, что спрашивающий хочет, чтобы программа работала иначе, предположительно, если у нее есть определенные разрешения или нет, однако я бы сказал, что проверка sudo - это не способ сделать это. Во-первых, многие системы могут не реализовывать «sudo», это ни в коем случае не требуется в Linux или многих Unixes.

Например, пользователь уже может войти в систему как пользователь root, что делает sudo бессмысленным, или, возможно, в системе есть пользователи без полномочий root, у которых все еще есть возможности для выполнения административных задач, которые программа может пожелать выполнить. Наконец, возможно, система вообще не имеет рута или sudo и вместо этого использует систему обязательного контроля доступа с различными возможностями и не может поймать всех суперпользователей, в которых может быть sudo. Или пользователь может быть заблокирован, но в учетную запись, которая имеет -less-разрешения, чем их собственная учетная запись по соображениям безопасности (я часто запускаю ненадежный код с временным непривилегированным пользователем, который может писать только на ramdisks, чтобы удалить, а не поднять мои разрешения ). В целом плохая идея предполагать наличие конкретной модели разрешений, такой как sudo или существование root, или предполагать, что sudoed-пользователь имеет какие-то особые привилегии.

Если вы хотите выяснить, есть ли у вас разрешения на выполнение операции, лучше всего просто попытаться сделать это, а затем проверить errno на наличие проблем с разрешениями, если она завершится неудачно или если это многоэтапная операция, которая должна либо завершиться неудачей, либо завершиться успешно. вы можете проверить, будет ли операция работать с такими функциями, как функция доступа POSIX (остерегайтесь возможных условий гонки здесь, если разрешения активно изменяются)

Если, кроме того, вам необходимо знать реального пользователя, стоящего за sudo, вы можете использовать функцию getlogin, которая должна работать для любого интерактивного сеанса с нижележащим терминалом и позволит вам, например, найти, кто «в действительности» выполняет команду для аудита, или найти Домашний каталог реального пользователя для сохранения логов.

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

Vality
источник
7

Есть два механизма, которые можно использовать.

  • Проверка переменных среды может быть сфальсифицирована в любом случае, но это проще всего сделать. growisofsне любит работать под SUDO, поэтому я отменяю переменные SUDO в сценариях, где я его использую. Это может быть подделано другим способом. (Переменная SUDO также переносится в среду для сценариев, запускаемых с помощью команд at и batch.)
  • Другой способ проверить, работает ли вы под sudo, - это просмотреть список процессов из родительского процесса в поисках sudo. Было бы трудно скрыть, что вы работали под sudo таким образом, но это более сложно. Все еще возможно притворяться, что вы работаете под sudo.

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

BillThor
источник
1
> Было бы трудно скрыть, что вы работали под sudo таким образом. Не могли бы вы просто переименовать sudoбинарный файл во что-то другое? Или назвать какой-нибудь другой исполняемый файл, sudoчтобы имитировать противоположное? Не то чтобы я действительно ожидал, что кто-нибудь вменяемый сделает это ...
Боб
@Bob Вам понадобится rootдоступ для переименования sudoисполняемого файла. Обычный пользователь не сможет этого сделать. Я заметил, что вы можете подделать, что вы работаете под sudo. Переименование существующей программы будет работать. Код, необходимый для специальной фальшивой sudoпрограммы, тривиален.
BillThor
Вы можете просто скачать бинарный файл sudo откуда-нибудь и дать ему необходимые разрешения ...
Jens Timmerman
@JensTimmerman Вам нужны права суперпользователя, чтобы предоставить ему соответствующие права. Если вы можете просто переименовать его или жестко связать его. Нет необходимости скачивать его. Если вы устанавливаете его SUID для идентификатора целевого пользователя (если он будет работать таким образом), вы должны уже скомпрометировать идентификатор целевого пользователя.
BillThor
ах, верно, он отказывается работать без setuid, мой плохой ...
Дженс Тиммерман
2

Вы можете сравнить эффективный и реальный идентификатор пользователя.

Это не обязательно означает, что он выполняет отмену sudo (также может быть установлено setuid'd), но указывает на то, что программа имеет больше прав, чем может ожидать пользователь. (например, в программе, которая обычно выполняется без таких прав, но должна запускаться с ними во время установки или для установки обновлений. Затем вы можете использовать это, чтобы дать несколько предупреждений об этом).

blabla999
источник
2
Нет, sudoустанавливает как эффективный, так и реальный идентификатор. В отличие от suid, чего нет. Вот тривиальная программа на 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.
Стивен С.
@ StefhenC - я думаю, что для целей ОП нет никакой разницы. ИМХО, их цель - идентифицировать выполнение sudo или выполнение из аутентичной корневой оболочки без каких-либо различий.
Элиран Малка
1
Я думаю, что вы можете быть правы. Я пришел сюда, потому что не понимал, почему sudo echo $USERпечатает непривилегированное имя пользователя (переменная подставляется ДО sudo). Я фактически закончил тем, что использовал ваш код в моем сценарии. Спасибо!
Стивен С
Добро пожаловать :)
Элиран Малка
-1

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

Проверка кода ошибки (или кода возврата) после rm не позволяет кому-либо вручную использовать полномочия sudo для создания файла, чтобы разыграть вас.

Крис К
источник
4
Этот ответ проверяет, есть ли у процесса разрешение на запись /root(что не обязательно совпадает с выполнением с UID 0), но не проверяет, получил ли он эти разрешения, используя sudo.
Ладададада
Да, «тысяча способов убрать кошку»; когда я писал ответ, я думал о 4 или 5 вещах, поэтому я обернул его.
Крис К
-2

Я обнаружил, что это хорошо работает для этого

[ $(cat /proc/$PPID/loginuid) -ne 0 ] && [ "$USER" == "root" ]
ruckc
источник
Это не работает, когда я пробую это на FreeBSD, Centos7 или MacOS X. Я думаю, что вы имеете в виду «/ proc» вместо «/ etc». Но даже с этим изменением, оно не работает ни на одном из этих трех. $ USER сбрасывается с помощью sudo. Вы имели в виду $ SUDO_USER? Кроме того, вы имели в виду "[[" вместо "["?
TomOnTime
1
я исправил пример. в основном проверка на логин не равна 0, но пользователь root.
ruckc