Всем привет. Мы активно вливаемся в работу и уже в январе готовим много мощных запусков. Среди прочих, объявлен набор на новый поток полюбившегося всем курса
Файловые разрешения предлагают безопасную альтернативу исполняемым файлам SUID, но могут показаться немного запутанными на первый взгляд.
Все мы знаем, что двоичные файлы
Я сэкономлю вам время, если вы хотите избежать подробного прочтения статьи выше: в сущности, файловые разрешения позволяют процессам, которые запускаются от имени root-пользователя и, следовательно, имеют право что-либо делать, сохранять определенные возможности, ограниченные
Разрешения отлично подходят для сервисов, которые обычно всегда запускаются от имени root-пользователя, но как насчет утилит командной строки? К счастью, это так же поддерживается при условии, что у вас установлены правильные утилиты. Если вы используете Ubuntu, вам, например, понадобится пакет libcap2-bin
. Вам также нужно будет запустить не архаичное ядро (начиная с версии 2.6.24).
Эти функции позволяют связывать разрешения с исполняемыми файлами аналогично настройке бита SUID, но только для определенного набора разрешений. Утилита setcap
используется для добавления и удаления разрешений из файла.
Первый шаг — выбрать нужные вам разрешения. Для этой статьи я предполагаю, что существует инструмент диагностики сети, называемый tracewalk
, который должен уметь использовать CAP_NET_RAW
.
Предполагая, что вы находитесь в каталоге, где расположен двоичный файл tracewalk
, вы можете добавить это разрешение следующим образом:
sudo setcap cap_net_raw=eip tracewalk
Пока проигнорируйте суффикс =eip
для разрешения, я расскажу об этом через пару секунд. Обратите внимание, что имя разрешения в нижнем регистре. Теперь вы можете проверить, правильно ли вы настроили разрешения, с помощью:
setcap -v cap_new_raw=eip tracewalk
Или вы можете вывести список всех разрешений, установленных для данного исполняемого файла:
getcap tracewalk
Для справки, вы также можете удалить все разрешения из исполняемого файла с помощью:
setcap -r tracewalk
На этом этапе вы должны иметь возможность запускать исполняемый файл как непривилегированный пользователь, и он должен иметь возможность работать с необработанными сокетами, но не иметь никаких других привилегий, которыми обладает root-пользователь.
Итак, что означает этот странный суффикс =eip
? Здесь потребуется толика понимания природы разрешений. Каждый процесс имеет три набора разрешений — эффективные, наследуемые и доступные (effective, inheritable и permitted):
- Эффективные (Effective) разрешения — это те, которые определяют, что процесс может на самом деле делать. Например, он не может иметь дело с необработанными сокетами, если
CAP_NET_RAW
не находится в эффективном наборе. - Доступные (Permitted) разрешения — это те, которые разрешено иметь процессу, если он запрашивает их с помощью соответствующего вызова. Они не позволяют процессу фактически что-либо делать, если только он не был специально написан для запроса указанного разрешения. Это позволяет писать процессы для добавления особо важных разрешений в эффективный набор только на тот период, когда они действительно требуются.
- Наследуемые (Inheritable) разрешения — это те, которые могут быть унаследованы в доступном наборе порожденного дочернего процесса. Во время операции
fork()
илиclone()
дочернему процессу всегда дается копия разрешений родительского процесса, поскольку в этот момент он все еще выполняет тот же исполняемый файл. Наследуемый набор используется, когдаexec()
(или аналог) вызывается для замены исполняемого файла другим. На этом этапе доступный набор процесса маскируется наследуемым набором для получения доступного набора, который будет использоваться для нового процесса.
Таким образом, утилита setcap
позволяет нам добавлять разрешения этих трех наборов независимо для данного исполняемого файла. Обратите внимание, что значение групп интерпретируется немного по-разному для прав доступа к файлам:
- Доступные файловые разрешения — это те, которые всегда доступны для исполняемого файла, даже если родительский процесс, который вызвал его, не имел их. Раньше их называли «принудительными» разрешениями.
- Наследуемые файловые разрешения определяют дополнительную маску, которая также может использоваться для удаления разрешений из набора вызывающего процесса. Они применяются в дополнение к наследуемому набору вызывающего процесса, поэтому разрешение наследуется только в том случае, если она существует в обоих наборах.
- Эффективные файловые разрешения на самом деле представляет собой всего лишь один бит, а не набор, и если он установлен, то это означает, что весь доступный набор также копируется в эффективный набор нового процесса. Это может быть использовано для добавления разрешений к процессам, которые не были специально написаны для их запроса. Поскольку это один бит, если вы устанавливаете его для какого-либо разрешения, он должен быть установлен для всех разрешений. Вы можете думать о нем как об легаси бите, потому что он используется, чтобы разрешить использование разрешений для приложений, которые их не поддерживают.
При указании разрешений через setcap
три буквы e
, i
и p
относятся к эффективному, наследуемому и доступному множествам соответственно. Итак, более ранняя спецификация:
sudo setcap cap_net_raw=eip tracewalk
… указывает, что разрешение CAP_NET_RAW
должно быть добавлено к доступным и наследуемым наборам и что также должен быть установлен эффективный бит. Это заменит любые ранее установленные разрешения в файле. Чтобы установить сразу несколько разрешений, используйте список через запятую:
sudo setcap cap_net_admin,cap_net_raw=eip tracewalk
Во-первых, файловые возможности не работают с симлинками — вы должны применить их к самому двоичному файлу (то есть к цели симлинка).
Во-вторых, они не работают с интерпретируемыми скриптами. Например, если у вас есть скрипт Python, которому вы хотите назначить разрешение, вы должны назначить его самому интерпретатору Python. Очевидно, что это потенциальная проблема безопасности, потому что тогда все скрипты, выполняемые с этим интерпретатором, будут иметь указанное разрешение, хотя это все же значительно лучше, чем сделать SUID. Наиболее распространенный обходной путь, по-видимому, заключается в написании отдельного исполняемого файла на C или аналоге, который может выполнять необходимые операции и вызывать его из скрипта. Это похоже на подход, используемый Wireshark, который использует двоичный файл /usr/bin/dumpcap
для выполнения привилегированных операций:
$ getcap /usr/bin/dumpcap
/usr/bin/dumpcap = cap_net_admin,cap_net_raw+eip
В-третьих, файловые разрешения отключаются, если вы используете переменную среды LD_LIBRARY_PATH
по понятным причинам безопасности(1). То же самое относится и к LD_PRELOAD
, насколько я знаю.
1. Поскольку злоумышленник, очевидно, может подменить одну из стандартных библиотек и использовать LD_LIBRARY_PATH
, чтобы заставить свою библиотеку вызываться в предпочтении перед системной, и, следовательно, иметь собственный произвольный код, выполняемый с теми же привилегиями, что и вызывающее приложение.
На этом все. Подробно о программе курса, можно будет узнать на
Источник: habr.com