Это третья статья из цикла
И сегодня она попала в поток «Администрирование». Сегодня мы не будем писать модули или настраивать RBAC, а пойдем по пути наименьшего сопротивления и просто захарденим обычный LAMP-сервер при помощи готовой политики, включив необходимые настройки.
Если кто забыл, за аббривиатурой LAMP скрывается Linux, Apache, Mysql, PHP, т.е. это большая часть всех
Предположения
Итак, предполагаем, что:
- Дистрибутив — CentOS 7 x64, пользователь — root
- SELinux включен, загружена политика targeted
- Режим SELinux — enforcing
Подготовка
Если LAMP у вас уже установлен и настроен — можете пропустить
Установим стандартный комплект софта для LAMP:
[root@lamp ~]# yum install -y httpd mariadb-server php-fpm php-mysql
Минимально настроим софт:
listen = 127.0.0.1:9009
user = apache
group = apache
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
pm.status_path = /status
request_terminate_timeout = 10s
request_slowlog_timeout = 1s
slowlog = /var/log/php-fpm/www-slow.log
security.limit_extensions = .php
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 128M
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session
UserDir enabled
UserDir www
</IfModule>
<Directory "/home/*/www">
AllowOverride FileInfo AuthConfig Limit Indexes
Options MultiViews Indexes
Require method GET POST OPTIONS
DirectoryIndex index.html index.htm index.php
<FilesMatch ".php$">
<If "-f %{REQUEST_FILENAME}">
SetHandler "proxy:fcgi://127.0.0.1:9009"
</If>
</FilesMatch>
</Directory>
Запустим все необходимые сервисы:
[root@lamp ~]# systemctl enable httpd mariadb php-fpm
[root@lamp ~]# systemctl start httpd mariadb php-fpm
Добавим какого-нибудь пользователя, например phpbb:
[root@lamp ~]# useradd -Z user_u -m -g apache phpbb
[root@lamp ~]# chmod 750 /home/phpbb
И создадим простой тестовый файл с phpinfo():
[phpbb@lamp ~]$ mkdir www
[phpbb@lamp ~]$ echo "<?php phpinfo(); ?>" > www/info.php
Перейдем по ссылке…
… и получим именно то, что получают все :)
Разбираемся с ошибками
В отличие от других мануалов, где следующим шагом идет «отключите SELinux», мы сейчас узнаем, почему так получилось и что можно сделать.
Для начала — установим консольные утилиты для управления политиками SELinux:
[root@lamp ~]# yum install -y policycoreutils-python policycoreutils-newrole policycoreutils-restorecond setools-console
А потом — включим нужные нам модули ( командой semodule ):
[root@lamp ~]# semodule -e apache
[root@lamp ~]# semodule -e mysql
Давайте посмотрим, с какими именно проблемами столкнулся apache при открытии этой страницы?
#!!! This avc can be allowed using one of the these booleans:
# httpd_enable_homedirs, httpd_read_user_content, httpd_unified
allow httpd_t httpd_user_content_t:file getattr;
Все верно: папка www ( а так-же папки web и public_html ) внутри домашней директории пользователя автоматически получает тип httpd_user_content_t, что и указано в правилах:
type_transition user_t user_home_dir_t: dir httpd_user_content_t «public_html»;
type_transition user_t user_home_dir_t: dir httpd_user_content_t «www»;
type_transition user_t user_home_dir_t: dir httpd_user_content_t «web»;
…
Лечение указано в выводе audit2allow, установка переменных выполняется командой setsebool ( или semanage boolean ).
[root@lamp httpd]# setsebool -P httpd_read_user_content=1
Обновляем страницу и получаем:
Смотрим логи:
[Tue Feb 28 21:15:04.555892 2017] [proxy_fcgi:error] [pid 21586] [client 192.168.56.101:57974] AH01079: failed to make connection to backend: 127.0.0.1
Все ясно: httpd не может коннектиться куда попало, httpd может ходить только куда нужно. Это логично: если веб-сервер вдруг соединяется по ssh, то явно происходит что-то странное.
Давайте посмотрим, куда веб-серверу ходить можно?
DT allow httpd_t mythtv_port_t: tcp_socket name_connect; [ httpd_can_connect_mythtv ]
DT allow httpd_t zabbix_port_t: tcp_socket name_connect; [ httpd_can_connect_zabbix ]
DT allow httpd_t smtp_port_t: tcp_socket name_connect; [ httpd_can_sendmail ]
DT allow httpd_t mssql_port_t: tcp_socket name_connect; [ httpd_can_network_connect_db ]
DT allow httpd_t postgresql_port_t: tcp_socket name_connect; [ httpd_can_network_connect_db ]
ET allow httpd_t ocsp_port_t: tcp_socket name_connect; [ kerberos_enabled ]
DT allow httpd_t oracle_port_t: tcp_socket name_connect; [ httpd_can_network_connect_db ]
DT allow httpd_t gopher_port_t: tcp_socket name_connect; [ httpd_can_network_relay ]
DT allow httpd_t osapi_compute_port_t: tcp_socket name_connect; [ httpd_use_openstack ]
DT allow httpd_t mongod_port_t: tcp_socket name_connect; [ httpd_can_network_connect_db ]
DT allow httpd_t memcache_port_t: tcp_socket name_connect; [ httpd_can_network_relay ]
DT allow httpd_t memcache_port_t: tcp_socket name_connect; [ httpd_can_network_memcache ]
DT allow httpd_t http_cache_port_t: tcp_socket name_connect; [ httpd_can_network_relay ]
DT allow httpd_t cobbler_port_t: tcp_socket name_connect; [ httpd_can_network_connect_cobbler ]
DT allow httpd_t ftp_port_t: tcp_socket name_connect; [ httpd_can_connect_ftp ]
DT allow httpd_t ftp_port_t: tcp_socket name_connect; [ httpd_can_network_relay ]
DT allow httpd_t gds_db_port_t: tcp_socket name_connect; [ httpd_can_network_connect_db ]
DT allow httpd_t pop_port_t: tcp_socket name_connect; [ httpd_can_sendmail ]
DT allow httpd_t http_port_t: tcp_socket name_connect; [ httpd_can_network_relay ]
ET allow httpd_t http_port_t: tcp_socket name_connect; [ httpd_graceful_shutdown ]
ET allow httpd_t kerberos_port_t: tcp_socket name_connect; [ kerberos_enabled ]
DT allow httpd_t ldap_port_t: tcp_socket name_connect; [ httpd_can_connect_ldap ]
DT allow httpd_t ephemeral_port_type: tcp_socket name_connect; [ httpd_use_openstack ]
DT allow httpd_t ephemeral_port_type: tcp_socket name_connect; [ httpd_can_connect_ftp ]
DT allow httpd_t ephemeral_port_type: tcp_socket name_connect; [ httpd_can_network_relay ]
DT allow httpd_t squid_port_t: tcp_socket name_connect; [ httpd_can_network_relay ]
DT allow httpd_t mysqld_port_t: tcp_socket name_connect; [ httpd_can_network_connect_db ]
В квадратных скобках указаны переменные, которые отвечают за работу этого правила.
Итого: нужно добавить порт 9009 в один из типов, к которым разрешен коннект, а затем установить переменную httpd_can_network_relay в 1.
Новый порт добавляется при помощи команды semanage port:
[root@lamp httpd]# semanage port -a -t http_cache_port_t -p tcp 9009
[root@lamp httpd]# setsebool -P httpd_can_network_relay=1
Обновляем страницу и видим:
Что-то посложнее
Давайте теперь усложним задачу и поставим phpbb на этот хост.
[phpbb@lamp ~]$ unzip phpBB-3.2.0.zip
[phpbb@lamp ~]$ mv phpBB3/* www/
[phpbb@lamp ~]$ restorecon -R www/
Попробуем создать для себя базу:
[phpbb@lamp www]$ mysql -uroot
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (13)
Поищем, как разрешить пользователю соединяться с базой?
DT allow user_t mysqld_db_t: dir { getattr search open }; [ selinuxuser_mysql_connect_enabled ]
DT allow user_t mysqld_t: unix_stream_socket connectto; [ selinuxuser_mysql_connect_enabled ]
DT allow user_t mysqld_t: unix_stream_socket connectto; [ selinuxuser_mysql_connect_enabled ]
DT allow user_t mysqld_var_run_t: sock_file { write getattr append open }; [ selinuxuser_mysql_connect_enabled ]
DT allow user_t mysqld_var_run_t: sock_file { write getattr append open }; [ selinuxuser_mysql_connect_enabled ]
Отлично, включаем selinuxuser_mysql_connect_enabled и продолжаем:
[root@lamp httpd]# setsebool -P selinuxuser_mysql_connect_enabled=1
Создаем базу и пробуем зайти в инсталляшку phpbb:
Почему так? Потому что httpd не может изменять пользовательские данные. Давайте узнаем, какие же он изменять может?
ET allow httpd_t httpd_user_ra_content_t: dir { ioctl write getattr lock add_name search open }; [ httpd_builtin_scripting ]
ET allow httpd_t httpd_user_ra_content_t: dir { ioctl write getattr lock add_name search open }; [ httpd_builtin_scripting ]
ET allow httpd_t httpd_user_rw_content_t: dir { ioctl read write getattr lock add_name remove_name search open }; [ httpd_builtin_scripting ]
ET allow httpd_t httpd_user_rw_content_t: dir { ioctl read write getattr lock add_name remove_name search open }; [ httpd_builtin_scripting ]
ET allow httpd_t httpd_user_rw_content_t: dir { ioctl read write create getattr setattr lock unlink link rename add_name remove_name reparent search rmdir open }; [ httpd_builtin_scripting ]
ET allow httpd_t httpd_user_rw_content_t: dir { ioctl read write getattr lock add_name remove_name search open }; [ httpd_builtin_scripting ]
DT allow httpd_t user_tty_device_t: chr_file { ioctl read write getattr lock append }; [ httpd_tty_comm ]
ET allow httpd_t httpd_user_rw_content_t: sock_file { read write getattr append open }; [ httpd_builtin_scripting ]
DT allow httpd_t user_devpts_t: chr_file { ioctl read write getattr lock append }; [ httpd_tty_comm ]
ET allow httpd_t httpd_user_rw_content_t: lnk_file { ioctl read write create getattr setattr lock append unlink link rename }; [ httpd_builtin_scripting ]
Устанавливаем php-xml, включаем httpd_builtin_scripting и назначаем контекст httpd_user_rw_content_t на указанные файлы и папки ( командой chcon ):
[root@lamp httpd]# setsebool -P httpd_builtin_scripting=1
[phpbb@lamp www]$ chmod 660 config.php
[phpbb@lamp www]$ chcon -t httpd_user_rw_content_t cache/ store/ files/ config.php images/avatars/upload/
Получаем:
Устанавливаем phpBB дальше, удаляем install и получаем работающий форум:
Меняем контекст конфига обратно:
[phpbb@lamp www]$ chcon -t httpd_user_content_t config.php
Наслаждаемся безопасным форумом :)
Вместо послесловия
Не написав ни одной строчки кода, используя только знания из man-файлов и стандартную политику SELinux по-умолчанию, можно за 30 минут настроить безопасное окружения для стандартных сервисов. И это не только про LAMP: стандартная политика содержит 403 готовых модуля. Этого хватит для решения большинства задач, которые когда-либо встанут перед администратором. Не выключайте SELinux, не заставляйте Дэна плакать.
Ссылка: ufile.io/5eced ( 846 Mb ) ( ссылка истечет 29.03.2017 )
phpbb:phpbb
mysql root:root
mysql phpbb:i6p0AYF1B4Hg
phpbb: kreon:kreon1
Команды
- semodule — управляет списком модулей
- sestatus — текущий статус SELinux
- setenforce 1/0 — включить/выключить enforcing
- audit2allow — утилита для генерации правил ( и для подсказок )
- sesearch — утилита для поиска правил в политике
- seinfo — показывает информацию о типах, ролях, атрибутах итд
- semanage — позволяет вносить изменения в политики
- chcon — позволяет менять контекст на ФС
- restorecon — востанавливает контекст по-умолчанию
- setsebool — устанавливает переменную в on/off. С -P — пишет на диск
- getsebool — получает переменную. -a — посмотреть все
Изменения политики
- semanage port -a/-d -t httpd_port_t -p tcp 8044 — добавить/удалить номер порта к контексту
- semanage fcontext -a/-d -t httpd_cache_t "/srv/http/cache(/.*)?" — добавить/удалить контекст для этой маски
- semanage permissive -a/-d httpd_t — включить/выключить режим permissive для httpd_t
Аргументы к командам
- id -Z — показывает контекст текущего пользователя
- ls -Z — показывает контекст файлов
- ps -Z — показывает контекст процессов
- netstat -Z — показывает контекст соединений
- usermod/useradd -Z связать пользователя с SELinux-пользователем
- ausearch -m AVC — показывает нарушения политик
Автор: kreon