Классическая модель доступа основана на том, что root может всё, а обычный пользователь может получить доступ к файлам, на которые установлены соответствующие права, а также отправить сигнал своим процессам. Повышение прав доступа обеспечивается специальными флагами в правах доступа (suid и sgid) на двоичные исполняемые файлы (не скрипты).
Современная модель доступа делит полномочия root на отдельные группы — capabilities. root имеет полный набор capabilities, но может отказаться от части из них. В дополнительные аттрибуты исполняемого файла вместо suid/sgid можно вписать получение тех или иных capabilities.
Классические права доступа в 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.h.
Количество capabilities в современных версиях ядра около 40. Точное количество можно узнать через интерфейс /proc
cat /proc/sys/kernel/cap_last_cap
Список текущих capabilities shell можно получить командой
capsh --print
cat /proc/<pid>/status | grep Cap
Эта команда выведет пять строк со значениями в виде набора двоичных флагов:
Пример вывода для команды 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> где
Подробнее этот формат описан в 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().
Какие бы права не были выставлены на файл, root будет иметь к нему доступ на чтение, запись и исполнение благодаря capability CAP_DAC_OVERRIDE
. То же справедливо для любого процесса, который получил эту capability. Например, для /bin/passwd достаточно было бы иметь CAP_DAC_OVERRIDE
для записи в /etc/passwd и /etc/shadow.
Есть тонкость, связанная с флагом на исполнение. Если флаг на исполнение не выставлен ни в одной из позиций (user, group, other), то root выполнить файл не может, а вот права типа --- --- --x
уже достаточны для выполнения файла.
Другие capabilities, связанные с правами доступа:
r-x
на все каталогиCAP_DAC_OVERRIDE
будет недостаточно.Программа 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