Мы — долго запрягаем, быстро ездим, и сильно тормозим.
www.lissyara.su —> статьи —> FreeBSD —> Security —> MAC + apache

Повышение уровня безопасности apache с использованием МАС

Автор: Al.


Данная статья не претендует на оригинальность и является неким пересказом хэндбука в вольном изложении. Целью данной статьи не является детальное описание всех политик МАС и принципов их работы.

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
default:\
....[color=red]\[/color]
:label=biba/high(low-high):

И обновляем bd
>cap_mkdb /etc/login.conf

Далее проверяем, что root в классе default или классе, его включающем (напр. russian)
>pw usershow root
root:*:0:0:default:0:0:Charlie &:/root:/bin/csh

Если нет, включаем его туда или правим класс. Сейчас проще включить
>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
>ps -axZ
....
biba/high(low-high)      1  ??  ILs    0:00,00 /sbin/init -s
....

Процесс init использует политику biba, работает с приоритетом high, с возможностью менять приоритет в пределах диапазона low-high

>getpmac
biba/high(low-high)

У нас приоритет high.

>getfmac /etc/login.conf
/etc/login.conf: biba/high

Все процессы и файлы имеют приоритет high.

Попробуем запустить csh с приоритетом low
>setpmac biba/low csh
>getpmac
biba/low(low-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]

Т.е. уровень доступа файлов, созданных в каталоге, будет понижен до уровня доступа вспомогательной градации(`[]`), указанного в уровне доступа родительского каталога.
Так же до этого уровня понижаются привелегии субъекта, порожденного этим объектом, если он является исполняемым.
>cp /usr/bin/top ./
>setfmac 'lomac/high[low]' top
>./top &
[1] 4716
>setpmac lomac/low csh
>getpmac -p 4716
lomac/low(low-high)

Некой особенностью тут является то, что работая с уровнем допуска high, мы не видим процессы, работающие под low.

Метка вида ``lomac/equal(equal-equal)'' может быть установлена на субъекты, которые используются для административного изменения меток в системе.

Сетевые интерфейсы
Интересные возможности дает установка меток на сетевые интерфейсы. По умолчанию при загрузке модуля они ставятся в
>ifconfig
re0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
...
        maclabel lomac/low(low-low)
...

И сетевые пакеты перестают бегать. Это дает достаточно широкое поле для экспериментов, но практического применения этой особенности я не придумал. НУ, можно разрешить каким-либо пользователям работать с сетью, а каким-то запретить. В нашем примере это не используется, поэтому выключаем сетевые интерфейсы из политики. Сделать это можно двумя способами:
>ifconfig re0 maclabel lomac/equal

Или
>cat /etc/sysctl.conf
security.mac.lomac.trust_all_interfaces=1

Лично пробовал первый.

Как это применительно к apache? Да очень просто. По минимуму, вся система у нас работает в high, процесс httpd и каталоги, куда он пишет (логи и сессии, например) в low. В случае взлома апача злоумышленник может изменять только файлы логов и того, что разрешено изменять апачу. Скажу сразу, если у вас крутится phpmyadmin и roundcube для локальных пользователей, то оно того, я думаю, не стоит.
И так, приступим.

Для начала необходимо загрузить сам модуль.
>cat /boot/loader.conf
mac_lomac_load="YES"

Так же необходимо исключить сетевые интерфейсы из политики. Пусть трафик на них будет бегать независимо от привелегий.
>grep bce /etc/rc.conf
ifconfig_bce0="inet 10.100.100.100/24 maclabel lomac/equal(equal-equal)"

Можно перезагрузиться и проверить, что все работает.

Далее готовим 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 меняем пути к лог-файлам
ErrorLog "/var/log/httpd/httpd-error.log"
CustomLog "/var/log/httpd/httpd-access.log" combined

И создаем под них директорию.
>mkdir /var/log/httpd/

ПОсле этого пробуем запустить-остановить апач с новым pid-файлом и путями к логам. Убеждаемся, что все нормально работает.

>/usr/local/etc/rc.d/apache22 start
>/usr/local/etc/rc.d/apache22 stop

Далее работаем над запуском apache с уровнем допуска low.
Все директории, куда пишет apache, должны иметь уровень доступа lomac/low[low]
>setfmac 'lomac/low[low]' /var/log/httpd/
>setfmac 'lomac/low[low]' /var/run/httpd/

Дальше несколько полезностей.
Что б без проблем работать с /tmp
>setfmac 'lomac/equal' /tmp/

В /var/tmp/ apache пишет сессии. Переназначить этот путь можно через php_admin_value session.save_path, что я и сделал. Для каждого виртуалхоста. В секциии виртуалхоста дописываем
php_admin_value session.save_path /var/tmp/session/vhost1

В этут папку должен иметь права на запись пользователь, от контого работает виртуалхост. Так же устанавливаем уровень доступа
>setfmac 'lomac/low(low-low)' /var/tmp/session/vhost1

Для загрузки файлов на ресурс иногда надо установить 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. Что и продемонстрируем.
>setpmac 'lomac/low(low-low)' csh
>getpmac
lomac/low(low-low)
>/usr/local/etc/rc.d/apache22 start
>ps -axZ | grep http | head -1
lomac/low(low-low) 36723 ?? SsJ 0:00,96 /usr/local/sbin/httpd -DNOHTTPACCEPT
>exit
exit
>getpmac
lomac/high(low-high)
>ps -axZ | grep http | head -1
>

Ну вот,впринципе, и все. Небольшой стартовый скрипт для запуска-остановки. Правим rc.conf
>grep apache22 /etc/rc.conf 
#apache22_enable="YES"
apache22_lomac_enable="YES"
apache22_pidfile="/var/run/httpd/httpd.pid"

Ну, и сам скрипт
>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 у меня были ошибки.

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

Небольшое дополнение. Например, при ротации логов апача newsyslog`ом, сервер не принимает сигнал на перечитывание конфигов и логи пишутся в старый. Или при использовании tail и grep одновременно для обработки логов возникает ошибка
#tail -f /var/log/httpd/httpd-access.log.0 | grep 1
tail: stdout: Permission denied
#

Лечится просто:
#setfmac 'lomac/equal[equal]' /var/log/httpd
#setfmac 'lomac/equal[equal]' /var/run/httpd

Источники:
http://www.freebsd.org/doc/ru_RU.KOI8-R/books/handbook/mac.html
man 4 mac
man 4 mac_mls
man 4 mac_biba
man 4 mac_lomac



размещено: 2011-11-08,
последнее обновление: 2012-05-16,
автор: Al




 

  Этот информационный блок появился по той простой причине, что многие считают нормальным, брать чужую информацию не уведомляя автора (что не так страшно), и не оставляя линк на оригинал и автора — что более существенно. Я не против распространения информации — только за. Только условие простое — извольте подписывать автора, и оставлять линк на оригинальную страницу в виде прямой, активной, нескриптовой, незакрытой от индексирования, и не запрещенной для следования роботов ссылки.
  Если соизволите поставить автора в известность — то вообще почёт вам и уважение.

© lissyara 2006-10-24 08:47 MSK

Время генерации страницы 0.2084 секунд
Из них PHP: 57%; SQL: 43%; Число SQL-запросов: 76 шт.
Исходный размер: 52748; Сжатая: 11752