Как защитить LAMP сервер на CentOS или RHEL

LAMP — это программный стек, состоящий из Linux (операционной системы, которая является базовым уровнем), Apache (веб-сервера, который «сидит сверху ОС), MySQL (или MariaDB, системы управления реляционной базой данных) и, наконец, PHP (скриптовый язык на стороне сервера, который используется для обработки и отображения информации сохранённой а базе данных).

В этой статье мы предполагаем, что каждый компонент стека LAMP уже установлен и запущен, и мы сфокусируемся исключительно на защите LAMP сервера(ов). Мы должны помнить, тем не менее, что защита на стороне сервера — это очень обширная тема и, следовательно, не может быть решена должным образом и полностью в одной статье.

В этом посте мы осветим базовые, необходимые действия для защиты каждой части стека.

Защита Linux

Так как, возможно, вы хотите управлять вашим сервером CentOS через ssh, вам нужно рассмотреть следующий совет по безопасности удалённого доступа к серверу, отредактировав файл /etc/ssh/sshd_config file.

1) Используйте всегда, когда это возможно, аутентификацию основанную на ключе вместо базовой аутентификации (имя пользователя + пароль) для удалённого входа на ваш сервер. Мы предполагаем, что вы уже создали пару ключей с вашим именем пользователя на вашей клиентской машине и скопировали его на ваш сервер (смотрите этот урок).

PasswordAuthentication no

RSAAuthentication yes

PubkeyAuthentication yes

2) Поменяйте порт, который будет прослушиваться sshd. Хорошая идея сделать номер порта выше чем 1024:

Port XXXX

3) Разрешите только протокол 2:

Protocol 2

4) Настройте аутентификационный таймаут, не разрешайте вход под рутом и ограничьте пользователей, который могут войти через ssh:

LoginGraceTime 2m

PermitRootLogin no

AllowUsers gacanepa

5) Разрешите только определённые хосты (и/или сети) для входа по ssh:

В файле the /etc/hosts.deny:

sshd: ALL

В файле the /etc/hosts.allow:

sshd: XXX.YYY.ZZZ. AAA.BBB.CCC.DDD

где XXX.YYY.ZZZ. Представляет первые 3 байта (октета) сетевого адреса IPv4, а AAA.BBB.CCC.DDD это IPv4 адрес. С этими настройками только хосты из сети XXX.YYY.ZZZ.0/24 и хосты AAA.BBB.CCC.DDD будут допущены для связи через ssh. Все другие хосты будут отключены до того, как они получат приглашение на ввод учётных данных и получат ошибку вроде этой:

14849749988_4ca4a9a88a_o

(Не забудьте перезагрузить демон sshd, чтобы изменения вступили в силу: service sshd restart).

Мы должны отметить, что такое решение — быстрый, но, в некоторой степени, рудиментарный способ блокировки входящих соединений на ваш сервер. Для дальнейшей настройки, масштабирования и гибкости вам следует рассмотреть использование простых iptables и/или fail2ban.

Защита Apache

1) Убедитесь, что системный пользователь, под которым запущен веб-сервер Apache, не имеет доступа к шеллу:

# grep -i apache /etc/passwd

Если пользователь apache имеет дефолтный шелл (такой как /bin/sh), мы должны изменить это на /bin/false или /sbin/nologin:

# usermod -s /sbin/nologin apache

15035978382_fee4250910_o

Следующие предложения (со второго по пятый) относятся к файлу /etc/httpd/conf/httpd.conf:

2) Отключение листинга каталогов: это предотвратит отображение содержимого каталогов в браузере, если в каталоге отсутствует индексный файл (index.html, index.htm, index.php).

Удалите слово Indexes в директиве Options:

# The Options directive is both complicated and important. Please see

# http://httpd.apache.org/docs/2.2/mod/core.html#options

# for more information.

#

Options Indexes FollowSymLinks

Должно получиться:

Options None

15033494771_e64474a3fc_o

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

Следуя примеру выше, если мы рассмотрим настройки для каталога /var/www/icons, мы увидим, что "Indexes MultiViews FollowSymLinks" должны быть изменены на "None".

<Directory "/var/www/icons">
    Options Indexes MultiViews FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
<Directory "/var/www/icons">
    Options None
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
До После

3) Спрячьте версию Apache, а также информацию об модулях/ОС в сообщениях об ошибках (например, на странице, которая не найдена или запрещена для просмотра.

ServerTokens Prod # Это означает, что ответ http вернёт просто "Apache" но не номер версии

ServerSignature Off # Информация об ОС спрятана

14849688730_15a8263eaa_o

4) Отключите ненужные модули, закомментировав линии, где эти модуля декларируются:

15036344595_37c2c3f685_o

ПОДСКАЗКА: отключение autoindex_module — это другой способ спрятать листинг каталогов в которых нет индексного файла.

5) Ограничьте размер HTTP запроса (тело и заголовки) и установите таймаут соединения:

Директива Контекст Пример и значение
LimitRequestBody серверный config, virtual host, directory, .htaccess Ограничьте размер выгружаемого файла максимальными 100 KiB. для директории выгрузки:

<Directory "/var/www/test/uploads">
   LimitRequestBody 102400
</Directory>

Эта директива определяет размер байт с 0 (значит неограничено) до 2147483647 (2GB), что разрешено в теле запроса.

LimitRequestFieldSize серверный config, virtual host Измените разрешённый размер заголовок HTTP запроса на 4KiB (по умолчанию — 8KiB), серверная ширина:

LimitRequestFieldSize 4094

Эта директива определяет величину байтов, которая разрешена в заголовке запроса HTTP и даёт администратору лучший контроль над ненормальным поведением клиентских запросов, которые могут быть полезны для избежания некоторых форм атак отказа в обслуживании.

TimeOut серверный config, virtual host Измените таймаут с 300 (это значение по умолчанию, если не задана величина) на 120:

TimeOut 120

Количество времени в секундах, сервер будет ждать определённых событий перед сбросом запроса.

Ещё больше директив и инструкций, а также информацию по их настройке вы найдёте в документации Apache.

Защита MySQL сервера

Мы начнём с запуска скрипта mysql_secure_installation, который поставляется с пакетом mysql-server.

1) Если мы не установили пароль рута для MySQL сервера во время установки, сейчас самое время сделать это, и помните: это основа в производственной среде.

14849606679_5a39bed329_o

Процесс продолжается:

14849798007_d7e42fc0b6_o

2) Удалите анонимного пользователя:

15035978272_444f718428_o

3) Разрешите рут доступ только с локалхоста:

15036344545_97c3c2fb01_o

4) Удалите дефолтную базу данных под названием test:

15013347206_3c3c37374c_o

5) Примените изменения:

15013347216_338ff6a59c_o

6) Следующее, мы отредактируем некоторые переменные в файле

[mysqld]

bind-address=127.0.0.1 # MySQL будет принимать соединения только с localhost

local-infile=0 # Отключение прямого доступа к файловой системе

log=/var/log/mysqld.log # Включение лог файла, чтобы видеть зловредную активность

Не забудьте перезапустить MySQL сервер с 'service mysqld restart'.

Сейчас, когда мы пришли к рутинному администрированию базой данных, вы найдёте следующие предложения полезными:

  • Если по каким-то причинам нам нужно управлять базой данных удалённо, мы можем делать это, вначале, соединившись через ssh к нашему серверу для выполнения необходимых запросов и административных задач локально.
  • Мы можем захотеть включить прямой доступ к файловой системе позже, например, если нам нужно выполнить массовый импорт файлов в базу данных.
  • Храните логи, это не так критично, как первые две вещи упомянутые ранее, но может пригодиться для решения проблем нашей базы данных и/или быть в курсе незнакомой деятельности.
  • НИКОГДА НЕ сохраняйте чувствительную информацию (такую как пароли, номера кредитных карт, банковские ПИНы — названо только несколько примеров) в простом текстовом формате. Подумайте об использовании функций хэша для обфускации этой информации.
  • Убедитесь, что специфичные для приложений базы данных могут быть доступны только соответствующим пользователям, которые были созданы приложением для этой цели.

Для настройки разрешений доступа пользователей MySQL, используйте эти инструкции.

Вначале получите список пользователей из таблицы user:

[email protected]:~$ mysql -u root -p
Enter password: [Здесь ваш пароль рута]

mysql> SELECT User,Host FROM mysql.user;

15033290251_d2d4cb16f1_o

Убедитесь, что каждый пользователь имеет только доступ (и минимальные разрешения) к базе данных, которая ему нужна.

В следующем примере мы проверим разрешения пользователя db_usuario:

mysql> SHOW GRANTS FOR 'db_usuario'@'localhost';

14849606589_33d0964ea3_o

Вы можете отменять разрешения и доступ по мере необходимости.

Защита PHP

Поскольку эта статья ориентирована на безопасность компонентов стэка LAMP, мы не будем вдаваться в подробности, сколько озабоченности вызывает программная ипостась. Мы будем исходить из предположения, что наши веб-приложения безопасны, в том смысле, что разработчики должным образом выполнили свою задачу и убедились, что отсутствуют уязвимости, которые могут дать место для обычных атак, таких как XSS или SQL инъекции.

1) Отключите ненужные модули:

Мы можем отобразить листинг текущих модулей следующей командой: php -m

15033290341_2887a79a37_o

И отключите те, которые не нужны, либо удалением, либо переименованием соответствующего файла в каталоге /etc/php.d.

Например, поскольку расширение mysql стало устаревшим с версии PHP v5.5.0 (и будет удалено в будущем), мы можем захотеть отключить его:

# php -m | grep mysql

# mv /etc/php.d/mysql.ini /etc/php.d/mysql.ini.disabled

14849688510_8299ea0865_o

2) Спрячьте информацию о версии PHP:

# echo "expose_php=off" >> /etc/php.d/security.ini [или отредактируйте файл security.ini, если он уже существует]

15035978132_b1fefdfb08_o

3) Задайте open_basedir к нескольким специфичным каталогам (в php.ini), чтобы ограничеть доступ к базовой файловой системе:

14849606469_1f29a87ec9_o

4) Отключите удалённое выполнение кодов/команд, наряду с очень эксплуатируемыми функциями, такими как exec(), system(), passthru(), eval() и так далее (в php.ini):

allow_url_fopen = Off

allow_url_include = Off

disable_functions = "exec, system, passthru, eval"

15033290091_861b348888_o

14849606399_037d6dd5e8_o

Подведение итогов

1) Храните пакеты обновленными до их последних версий (сравнивайте вывод следующих команд с выводом 'yum info [package]'):

Следующие команды выведут текущие версии Apache, MySQL и PHP:

# httpd -v

# mysql -V (capital V)

# php -v

14849606449_a53b22b495_o

Затем 'yum update [package]' может быть использована для обновления пакета, чтобы иметь последние патчи безопасности.

2) Убедитесь, что конфигурационные файлы могут быть записаны только аккаунтом рута:

# ls -l /etc/httpd/conf/httpd.conf

# ls -l /etc/my.cnf

# ls -l /etc/php.ini /etc/php.d/security.ini

14849797647_c7719a81ff_o

3) Наконец, если у вас есть такая возможность, запустите эти сервисы (веб-сервер, сервер базы данных и сервер приложений) в отдельной физической или виртуальных машинах (и защитите связь между ними посредством файервола), т. е. в случае если один из них будет скомпрометирован, атакующий не будет иметь немедленного доступа к другим. В этом случае, возможно вам придётся изменить некоторые из конфигураций, описанных в этой статье. Помните, что это всего лишь некоторые примеры, которые могут быть использованы для увеличения безопасности на вашем LAMP сервере.

1 комментарий к “Как защитить LAMP сервер на CentOS или RHEL”

  1. Отличная статья, тут не предлагают включить глобальные переменные для php и отключить файрволл))

    Ответить

Оставьте комментарий