реальный=1000 действующий=1000 сохраненный=200

Когда процесс выполняет непривилегированную программу, действующий UID процесса становится сохраненным, в результате чего значения пользовательских идентификаторов будут иметь такой вид:

реальный=1000 действующий=200 сохраненный=1000

Избегайте выполнения командной оболочки (или другого интерпретатора) с повышенными привилегиями

Привилегированные программы, запущенные пользователем, никогда не должны запускать командную оболочку (напрямую или опосредованно, с помощью библиотечных функций system(), popen(), execlp(), execvp() и им подобных). Сложность и обширные возможности командных оболочек (и других многофункциональных интерпретаторов, таких как awk) делают практически невозможным устранение всех лазеек, связанных с безопасностью, даже если отключить интерактивный режим. Это, в свою очередь, дает возможность выполнять произвольные консольные команды от имени пользователя с действующим идентификатором процесса. Если вам необходимо запустить командную оболочку, заранее откажитесь от повышенных привилегий.

Пример бреши в безопасности, которая может возникнуть в результате запуска командной оболочки, приводится при описании функции system() в разделе 27.6.

Немногочисленные реализации UNIX учитывают биты с идентификаторами пользователя и группы, установленные для интерпретируемых скриптов (см. раздел 27.3); благодаря этому процесс, запускающий скрипт, исходит из того, что тот будет выполняться от имени какого-то другого (привилегированного) пользователя. Но ввиду рисков безопасности, описанных выше, Linux, как и некоторые другие UNIX-системы, просто игнорирует эти биты при выполнении скриптов. Но даже если система поддерживает установку UID и GID для скриптов, этой возможностью следует пренебрегать.

Закрывайте все ненужные файловые дескрипторы перед выполнением exec()

В разделе 27.4 отмечалось, что файловые дескрипторы по умолчанию остаются открытыми на протяжении всей работы вызова exec(). Привилегированная программа может открыть файл, недоступный обычным процессам. Полученный файловый дескриптор представляет привилегированный ресурс. Перед выполнением exec() он должен быть закрыт, чтобы запускаемая программа не смогла получить доступ к связанному с ним файлу. Для этого можно либо вручную закрыть файловый дескриптор, либо установить флаг FD_CLOEXEC (см. раздел 27.4).

38.4. Избегайте раскрытия деликатной информации

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

• Страница виртуальной памяти, содержащая данные, может быть сброшена на диск (если только она не была заблокирована с помощью вызова mlock() или аналогичного) и прочитана оттуда привилегированной программой.

• Процесс может сгенерировать файл с дампом памяти, получив соответствующий сигнал; этот файл может быть использован для получения данных.

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

По умолчанию Linux не разрешает программе, устанавливающей пользовательский идентификатор, генерировать дамп памяти в ответ на сигнал (см. раздел 22.1), даже если она отказалась от всех привилегий. Однако в других системах этот элемент безопасности может отсутствовать.

38.5. Изоляция процесса

В этом разделе мы рассмотрим различные способы изоляции программы, которые позволяют ограничить потенциальный ущерб в случае ее взлома.

Подумайте об использовании системы возможностей

В Linux существует система, позволяющая разделить традиционную для UNIX структуру привилегий («все или ничего») на отдельные элементы, которые называются возможностями. Возможности могут включаться и выключаться самим процессом в индивидуальном порядке. Выдавая программе нужные ей возможности, мы обеспечиваем ей менее широкие привилегии, чем если бы она выполнялась от имени администратора. Это снижает потенциал для нанесения вреда в случае ее взлома.

Кроме того, используя возможности в сочетании с битами безопасности, можно создать процесс, обладающий ограниченными функциями, однако не принадлежащий администратору (то есть ни один из его пользовательских идентификаторов не равен 0). Такой процесс больше не сможет применить функцию exec() для возвращения себе полного набора возможностей. Мы вернемся к этой теме в главе 39.

Перейти на страницу:

Похожие книги