Управление правами доступа

Классическая модель доступа основана на том, что root может всё, а обычный пользователь может получить доступ к файлам, на которые установлены соответствующие права, а также отправить сигнал своим процессам. Повышение прав доступа обеспечивается специальными флагами в правах доступа (suid и sgid) на двоичные исполняемые файлы (не скрипты).

Современная модель доступа делит полномочия root на отдельные группы — capabilities. root имеет полный набор capabilities, но может отказаться от части из них. В дополнительные аттрибуты исполняемого файла вместо suid/sgid можно вписать получение тех или иных capabilities.

ACL

Классические права доступа в Unix состоят из трёх разделов: User, Group, Other (ugo), в каждом из которых определяются три права на доступ к файлу: Read, Write, eXecute (rwx). При этом, в атрибутах файла прописан ровно один владелец (User) и одна группа (Group).

Для того, чтобы можно было назначать права на объекты в файловой системе (ФС) с точностью до пользователя были введены списки доступа (Access Lists, ACL). ACL позволяют связать с объектом ФС сколько угодно пользователей и групп, и назначить каждому свой набор прав rwx. Классические группы прав ugo считаются тремя элементами списка ACL, которые присутствуют в ACL всегда.

Просмотр ACL:

$ chmod 0644 /tmp/user1-tmp
$ getfacl /tmp/user1-tmp

getfacl: Removing leading '/' from absolute path names
# file: tmp/user1-tmp
# owner: user1
# group: users
user::rw-
group::r--
mask::rwx
other::r--

Установка ACL setfacl имеет две опции -m (modify) — добавить или изменить ACL и '-x' — удалить ACL.

$ setfacl -m user2:rwx /tmp/user1-tmp

$ getfacl /tmp/user1-tmp
getfacl: Removing leading '/' from absolute path names
# file: user1-tmp
# owner: user1
# group: user1
user::rwx
user:user2:rwx
group::rwx
mask::rwx
other::---

capabilities

В исходных текстах ядра список capabilities определён в файле capabilities.h.

Количество capabilities в современных версиях ядра около 40. Точное количество можно узнать через интерфейс /proc

cat /proc/sys/kernel/cap_last_cap

Список текущих capabilities shell можно получить командой

capsh --print

Просмотр capabilities процесса

cat /proc/<pid>/status | grep Cap

Эта команда выведет пять строк со значениями в виде набора двоичных флагов:

  • CapInh (Inheritable) — Наследуемые при загрузке исполняемого файла вызовом execve()
  • CapPrm (Permitted) — Текущий набор capabilities
  • CapEff (Effective)
  • CapBnd (Bounding set) — Ограничение на capabilities "сверху". Загрузка исполняемого файла не может добавить процессу capabilities сверх перечисленных
  • CapAmb (Ambient set)

Пример вывода для команды ping (pid 1234):

$ cat /proc/1234/status | grep Cap
CapInh: 0000000000000000
CapPrm: 0000000000003000
CapEff: 0000000000000000
CapBnd: 000001ffffffffff
CapAmb: 0000000000000000

Для декодирования двоичных флагов можно выполнить команду capsh --decode=<bits>:

$ capsh --decode=0000000000003000
0x0000000000003000=cap_net_admin,cap_net_raw

также можно воспользоваться командой getpcaps <pid>

$ getpcaps 1234
Capabilities for `1234': = cap_net_admin,cap_net_raw+p

Просмотр/установка аттрибутов исполняемого файла

$ getcap /usr/bin/ping
/usr/bin/ping = cap_net_admin,cap_net_raw+p

$ setcap cap_net_admin,cap_net_raw+p /usr/bin/ping

Формат задания capabilities в getcap/setcap имя1,имя2...<op><set> где

  • <op> — +, -, =
  • <set> — e, i, p (Effective, Inheritable, Permitted).

Подробнее этот формат описан в man 3 cap_from_text

Запуск приложений с помощью capsh.

Без ограничений

$ capsh -- -c "/usr/bin/ping -c 1 localhost"
PING localhost.localdomain (127.0.0.1) 56(84) bytes of data.
...

С отобранными capabilities

$ sudo capsh --drop=cap_net_raw -- -c "/usr/bin/ping -c 1 localhost"
ping: socket: Operation not permitted

Системные вызовы

Вызов capget для процесса с ping = 1234 (вывод strace)

$ strace -e capget getpcaps 1234
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=1234}, {effective=0, permitted=1<<CAP_NET_ADMIN|1<<CAP_NET_RAW, inheritable=0}) = 0

Установка capabilities делается вызовом capset().

Capabilities для доступа к файлу

Какие бы права не были выставлены на файл, root будет иметь к нему доступ на чтение, запись и исполнение благодаря capability CAP_DAC_OVERRIDE. То же справедливо для любого процесса, который получил эту capability. Например, для /bin/passwd достаточно было бы иметь CAP_DAC_OVERRIDE для записи в /etc/passwd и /etc/shadow.

Есть тонкость, связанная с флагом на исполнение. Если флаг на исполнение не выставлен ни в одной из позиций (user, group, other), то root выполнить файл не может, а вот права типа --- --- --x уже достаточны для выполнения файла.

Другие capabilities, связанные с правами доступа:

  • CAP_FSETID — позволяет копировать файлы с сохранением suid, sgid. Применяет sgid для процессов, которые не входят в группу, которой принадлежит файл
  • CAP_CHOWN — право на смену владельца и группы файла
  • CAP_DAC_READ_SEARCH — эквивалентно применению прав r-x на все каталоги
  • CAP_FOWNER — эквивалентно применения прав, которые обычно принадлежат только владельцу объекта, в том числе: chmod, управление ACL, запись в файлы в каталогах со stiky bit (/tmp). Для записи в чужие файлы в таком каталоге CAP_DAC_OVERRIDE будет недостаточно.

Программа sudo

Программа sudo предназначена для выполнения администрирования обычными пользователями

Способ запуска
sudo программа опции

Пользователь не должен знать пароль root'a, но, в зависимости от настроек, ему может быть предложено ввести свой пароль для авторизации. Беспарольный доступ обычно используют для повышения полномочий в скриптах, например для управления через Web. Для обычных администраторов пароль желательно оставлять, чтобы злоумышленник не воспользовался их правами, когда они на 5 минут отойдут от терминала.

Конфигурационный файл /etc/sudoers рекомендуется изменять редактором /usr/sbin/visudo. Visudo запускается с правами root, создает копию /etc/sudoers, затем, используя переменную среды EDITOR, запускает любимый редактор пользователя (или vi по умолчанию), а после редактирования проверяет результат на синтаксическую правильность и, в случае успешной проверки, сохраняет.

Формат файла sudoers:

пользователь на_компьютере=(под чьим именем) список команд

поле на_компьютере нужно для того, чтобы один файл sudoers можно было простым копированием размножать на различные машины

Пример файла /etc/sudoers, который разрешает пользователю user выполнять любые действия, подтверждая свои полномочия паролем, а пользователю apache позволяет выключить компьютер не вводя пароль.

user ALL=(ALL) ALL
apache ALL=(ALL) NOPASWD:/sbin/poweroff