Повышение уровня безопасности apache с использованием МАС
Данная статья не претендует на оригинальность и является неким пересказом хэндбука в вольном изложении. Целью данной статьи не является детальное описание всех политик МАС и принципов их работы.
FreeBSD 5.X представляет новые расширения системы безопасности от проекта TrustedBSD, основанные на документах POSIX®.1e. Два из наиболее важных нововведений в механизмах безопасности это списки контроля доступа файловой системы (Access Control Lists, ACLs) и принудительный контроль доступа Mandatory Access Control, MAC). Инфраструктура позволяет загружать новые модули контроля доступа, реализуя новые политики безопасности. Некоторые из них предоставляют защиту ключевых подсистем, защищая определенный сервис, в то время как другие предоставляют исчерпывающую систему безопасности с метками на всех субъектах и объектах. Контроль называется принудительным, поскольку применение контроля производится администраторами и системой, и не зависит от решения пользователей, как это происходит при обычном контроле доступа (Discretionary Access Control, DAC, стандартные файловые и System V IPC права в FreeBSD).
Существуют следующие политики. Все они подгружаются соответствующими модулями. Они могут быть использованы как совместно, так и отдельно друг от друга.
mac_seeotheruids - позволяет скрывать процессы, принадлежащие другим пользователям. mac_bsdextended - позволяте писать права на доступ к файлам в стиле брендмауэра. mac_ifoff - позволяет отключить сетевые интерфейсы. mac_portacl - ограничивает привязку (binding) к локальным портам TCP и UDP. mac_partition - распределяет процессы по ''разделам'' на основе их MAC меток. mac_mls - контролирует взаимодействие субъектов и объектов системы на основе правил. mac_biba - тоже, что и mac_mls, только с "перевернутой" иерархией доступа mac_lomac - тоже, что и mac_biba. С некоторыми дополнениями.
Рассмотрим политики mac_mls и mac_biba более детально. Политика mac_mls(4) контролирует взаимодействие субъектов и объектов системы путем применения строгой политики к потоку информации. Иными словами, мы можем объектам(файлам, сокетам) и субъектам(процессов, пользователей) ситемы назначить метки "секретности" и права доступа. Сравним нашу ОС с неким филиалом ФСБ. Есть сотрудники (субъекты), работающие с файлами (объектами). Для простоты понимания возьмем mac_mls. При данной политике сотрудник с уровнем допуска 7 не может читать файлы с уровнем доступа 15, поскольку они слишком секретны для него. Но он может записать туда свою информацию, так сказать, отправить сведения "на верх". В те же время он может читать любые файлы с уровнем доступа 1, но не может писать туда, т.к. его информация более секретна. Политика mac_biba отличается от mac_mls "перевернутой" иерархией доступа. субъект с низким уровнем целостности не может писать в субъект с высоким уровнем целостности; субъект с высоким уровнем целостности не может читать из субъекта с низким уровнем целостности. Для упрощенности администрирования максимально высокий уровени пишется как high, а максимально низкий - low. Так же можно задавать цифровые значения. Что бы убрать объект из политики, достаточно присвоить ему уровень equal.
И так, перейдем от теории к практике. Внимание: Неправильное использование информации этой главы может вызвать потерю доступа к системе, проблемы у пользователей, или невозможность запуска XFree86™. Что более важно, MAC не должен восприниматься как полная защита системы. Инфраструктура MAC лишь усиливает имеющуюся систему безопасности: без применения методов защиты и регулярных проверок, система никогда не станет полностью защищенной. От себя добавлю, что после некоторых эксперементов у меня перестали грузиться Х и на reboot выдавало что-то вроде reboot: SIGTSTP init: Permission denied. Если вы работаете удаленно, советую дочитать сначала до конца. Возможны варианты, когда доступ пользователей к сетевым подключениям будет запрещен (сеть перестанет работать). Подробнее в конце примеров.
Ядро должно быть собрано с поддержкой МАС. FreeBSD8 имеет эту попцию в GENERIC
options MAC
Далее необходимо загрузить сам модуль политики. Добавляем в /boot/loader.conf
mac_biba_load="YES"
Что б не случилось курьезов, root`а переводим сразу на уровень допуска high, с возможностью изменения в пределах low-high. Правим класс default в /etc/login.conf
Если нет, включаем его туда или правим класс. Сейчас проще включить
>pw usermod root -L default
Перезагружаемся и логинимся под root`ом.
Еще немного теории [man]getpmac [-p pid] - посмотреть уровень допуска процесса setpmac label command - запустить коммандуcommand с уровнем допуска label getfmac [-h] [-l lol] [file]- посмотреть уровень доступа файла setfmac [-h] [-l lol] [file]- установить уровень доступа файла[/man]
Проверяем. Теперь всем процессам присвоена метка high
При этом можно убедиться, что мы можем читать все файлы, права на чтение которых имеет root, а вот записать не можем ни один, несмотря на то, что права на запись так же имеются. Выходим из шела набрав exit. Пробуем установить метку.
>touch test
>setfmac biba/low test
setfmac: labeling not supported in test
Метки не поддерживаются. Включаем их на отмонтированном слайсе. Но в доках про это не слова. Есть только про ошибки /.
>tunefs -l enable /dev/ad8s1e
Пробуем заново
>touch test
>setfmac biba/low test
>getfmac test
test: biba/low
Далее запускаем csh с приоритетом low и пробуем писать и читать файл test
>setpmac biba/low csh
Удалить его не получится, т.к. для удаления нужны привелегии на каталог выше. Поэтому, работая под low, повышаем уровень доступа test до high, выходим, и удаляем его.
>getpmac
biba/low(low-high)
>setfmac biba/high ./test
>exit
exit
>rm test
Особый интерес представляет политика lomac. В целом, она схожа с biba, но дает одно преимущество - использование плавающих меток для поддержки понижения метки субъекта через вспомогательный отдел градации. Этот вспомогательный отдел принимает вид [auxgrade]. Это что-то вроде наследования привелегий. Правим /boot/loader.conf
>cat /boot/loader.conf
mac_lomac_load="YES"
И в /etc/login.conf меняем
:label=biba/high(low-high):
на
:label=lomac/high(low-high):
И обновляем bd
>cap_mkdb /etc/login.conf
Для вступления изменений в силу необходимо перезагрузиться.
Принцип работы объясню на примере.
>mkdir dir
>getfmac dir
dir: lomac/high
>touch dir/test1
>getfmac dir/test1
dir/test1: lomac/high
>setfmac 'lomac/low' dir
>getfmac dir
dir: lomac/low
>touch dir/test2
>getfmac dir/test1
dir/test2: lomac/high
Как видим из примера, независимо от уровня доступа родительского каталога dir, все файлы в нем создаются с уровнем доступа пользователя, который их создает, если он имеет на это право. В нашем случае я работаю под lomac/high. Но это не всегда удобно. Например, есть защищенный каталог, а в нем лежат незащищенный данные. Например, root хочет работать с какими-либо временнымти файлами web-сервера. Т.к. в моем случае httpd работает с привелегиями low, то данные, которые он может изменять, должны иметь уровень доступа тоже low. Если какие-либо файлы в этой директории будут созданы root`ом, они будут иметь уровень доступа high, как и root, и httpd после этого не сможет их изменять. В этом случае как раз и пригодится эта особенность lomac.
>getpmac
lomac/high(low-high)
>mkdir dir
>setfmac 'lomac/high[low]' dir
>touch dir/test
>getfmac dir/test
dir/test: lomac/low[low]
>getfmac dir
dir: lomac/high[low]
Т.е. уровень доступа файлов, созданных в каталоге, будет понижен до уровня доступа вспомогательной градации(`[]`), указанного в уровне доступа родительского каталога. Так же до этого уровня понижаются привелегии субъекта, порожденного этим объектом, если он является исполняемым.
И сетевые пакеты перестают бегать. Это дает достаточно широкое поле для экспериментов, но практического применения этой особенности я не придумал. НУ, можно разрешить каким-либо пользователям работать с сетью, а каким-то запретить. В нашем примере это не используется, поэтому выключаем сетевые интерфейсы из политики. Сделать это можно двумя способами:
Как это применительно к apache? Да очень просто. По минимуму, вся система у нас работает в high, процесс httpd и каталоги, куда он пишет (логи и сессии, например) в low. В случае взлома апача злоумышленник может изменять только файлы логов и того, что разрешено изменять апачу. Скажу сразу, если у вас крутится phpmyadmin и roundcube для локальных пользователей, то оно того, я думаю, не стоит. И так, приступим.
Для начала необходимо загрузить сам модуль.
>cat /boot/loader.conf
mac_lomac_load="YES"
Так же необходимо исключить сетевые интерфейсы из политики. Пусть трафик на них будет бегать независимо от привелегий.
Можно перезагрузиться и проверить, что все работает.
Далее готовим apache. Не забывая его перед этим остановить. Apache, работая под low, не сможет полноценно работать с директориями и файлами, имеющими уровень доступа high. Что бы не менять уровень доступа системных папок, создаем апачу свои папки. В конфиге меняем путь к pid-файлу.
PidFile "/var/run/httpd/httpd.pid"
Что бы rc.d скрипт видел новый pid в rc.conf дописываем
apache22_pidfile="/var/run/httpd/httpd.pid"
И в /usr/local/etc/rc.d/apache22 после
load_rc_config $name
Добавляем
eval pidfile="\${apache22_pidfile:-${pidfile}}"
Далее создаем папку для pid-файла.
>mkdir /var/run/httpd/
Так же необходимо переместить лог-файлы. В httpd.conf меняем пути к лог-файлам
Дальше несколько полезностей. Что б без проблем работать с /tmp
>setfmac 'lomac/equal' /tmp/
В /var/tmp/ apache пишет сессии. Переназначить этот путь можно через php_admin_value session.save_path, что я и сделал. Для каждого виртуалхоста. В секциии виртуалхоста дописываем
Для загрузки файлов на ресурс иногда надо установить php_admin_value upload_tmp_dirподобно примеру выше. Для отправки почты с сайтов разрешаем всем работать со спулом
>setfmac 'lomac/equal' /var/spool/clientmqueue
Меняем auxgrade на low для httpd, что бы все порождаемые им процессы имели уровень допуска low. На всякий случай.
>setfmac 'lomac/high[low]' /usr/local/sbin/httpd
Похоже, все. Пробуем запустить. Запуск должен производиться с допуском low-low. Для этого запускаем shell с не обходимым допуском. Далее все операции с apache будут производиться через него. Скаже больше, процессы httpd даже не будут видны из шела с уровнем допуска high. Что и продемонстрируем.
>cat rc.d/apache22_lomac
#!/bin/sh
# PROVIDE: apache22_lomac
# REQUIRE: DAEMON
# BEFORE: LOGIN
# KEYWORD: shutdown
if [ -z `egrep ^apache22_lomac_enable=\"[Ye][Ee][Ss]\" \
/etc/rc.conf` ]; then
echo "apache22_lomac is not enabled in rc.conf"
exit 1;
fi
command="/usr/sbin/setpmac lomac/low(low-low) /usr/local/etc/rc.d/apache22"
apache22_start() {
echo Starting apache in lomac/low
$command forcestart
}
apache22_command() {
echo Performing $1 command in lomac/low
$command $1
}
case $1 in
start)
apache22_start;;
quietstart)
apache22_start;;
stop)
apache22_command $1;;
restart)
apache22_command stop;
apache22_start;;
status)
apache22_command $1;;
reload)
apache22_command $1;;
configtest)
apache22_command $1;;
*)
echo "Usage: rc.d/apache22_lomac \
(start|stop|restart|status|reload|configtest)"
;;
esac
return 0;
Обратите внимание, что здесь есть переносы строки, в реально скрипте которых быть не должно. Это связано с ограничением длины строки кода на данном ресурсе. Некоторые спросят - почему не стал использовать /etc/rc.subr. Отвечу - при использовании данных фунцкий с setpmac у меня были ошибки.
Пример с реализацией писался уже после внедрения, так что могут быть неточности. С удовольствием выслушаю конструктивную критику и предложения по дополнению статьи.