Документация по ОС FreeBSD Воскресенье, 28.04.2024, 00:27
Приветствую Вас Гость | RSS
Меню сайта

Категории каталога
Apache [58]
DNS [25]
FTP [27]
Mail [74]
Samba [24]
Squid [46]
SSH [23]
VPN [35]
РРР [20]
Net [173]

Главная » Статьи » Сеть » Apache

Корень зла [2006]

Сегодня у нас на повестке дня вопросы, касающиеся обеспечения безопасности Web-сервера на базе OpenBSD. Мы научим PHP, MySQL и Sendmail работать с Apache, который запускается в окружении chroot - измененном корневом каталоге /var/www с правами непривилегированного пользователя www. Таким образом, нам удастся обеспечить дополнительный уровень защиты и максимально снизить возможный ущерб в том случае, если злоумышленнику окажется под силу взломать нашу систему. Применив полученные знания на практике, в твоем арсенале будет настолько защищенная система, что ты сможешь совершенно спокойно взяться за разработку любого проекта, будь то личный блог, новостной сайт компании или даже интернет-магазин с мириадами клиентов.

предварительный ликбез

Последняя версия ультрасекьюрной OpenBSD (3.9 на момент написания статьи) как нельзя лучше подойдет для выполнения нашей миссии. Короткая история взломов, прекрасная реализация стека TCP/IP, отличный файервол Packet Filter (pf), залатанный Apache 1.3.29 с поддержкой SSL, наличие последних версий OpenSSH и OpenSSL, тысячи добротно протестированных прекомпилированных пакетов - все это говорит в пользу сделанного выбора. Хотя стоит отметить, что в качестве используемой операционной системы может выступать любая из Free/Net/DragonFlyBSD.

За основу нашей конструкции примем PHP и MySQL. Не секрет, что за последние годы эта связка стала стандартом де-факто для интернет-проектов различного масштаба. Поэтому давай не будем на этом останавливаться и перейдем непосредственно к настройке.

каждой службе - свой раздел

Прежде всего, необходимо грамотно подойти к разделению дискового пространства. Лично я предпочитаю для каждой критически важной сетевой службы выделять собственный раздел. Для наглядности приведу содержимое конфига fstab(5) полностью:

# vi /etc/fstab

/dev/wd0a / ffs rw 1 1
/dev/wd1h /backup ffs rw,nodev,nosuid,softdep 1 2
/dev/wd1a /cvs ffs rw,nodev,nosuid 1 2
/dev/wd0g /export ffs rw,nodev,nosuid,softdep 1 2
/dev/wd1i /home ffs rw,nodev,nosuid,softdep 1 2
/dev/wd0d /tmp ffs rw,nodev,nosuid,noexec,softdep 1 2
/dev/wd0f /usr ffs rw,nodev,softdep 1 2
/dev/wd0e /var ffs rw,nodev,nosuid,softdep 1 2
/dev/wd1d /var/mail ffs rw,nodev,nosuid,noatime,softdep 1 2
/dev/wd1e /var/mysql ffs rw,nodev,nosuid,softdep 1 2
/dev/wd1f /var/squid ffs rw,nodev,nosuid,softdep 1 2
/dev/wd1g /var/www ffs rw,nodev,nosuid,softdep 1 2
/dev/wd1b none swap sw 0 0

Преимущества такой конфигурации видны даже невооруженным глазом:

- ПЕРЕПОЛНЕНИЕ ОДНОГО ИЗ РАЗДЕЛОВ НЕ ПОВЛИЯЕТ НА РАБОТУ БОЛЬШИНСТВА СЛУЖБ;
- ПРИ СЛУЧАЙНОМ ОТКЛЮЧЕНИИ ПИТАНИЯ ВО ВРЕМЯ ВЫПОЛНЕНИЯ ОПЕРАЦИИ ЗАПИСИ НА ОДНУ ИЗ ФАЙЛОВЫХ СИСТЕМ СНИЖАЕТСЯ ВОЗМОЖНОСТЬ ПОВРЕЖДЕНИЯ ОСТАЛЬНЫХ ФС;
- УВЕЛИЧЕНИЕ БЕЗОПАСНОСТИ СИСТЕМЫ ЗА СЧЕТ УКАЗАНИЯ ДЛЯ КАЖДОЙ ФС СПЕЦИАЛЬНЫХ ФЛАГОВ МОНТИРОВАНИЯ.

MySQL: записная книжка с SQL-интерфейсом

Теперь перейдем к установке и конфигурированию сервера баз данных. Собираем из портов три MySQL-пакета - client, server, tests:
 
# cd /usr/ports/databases/mysql
# make package

Для проверки правильности сборки выполняем набор прилагаемых тестов:

# make do-regress

Если все тесты прошли успешно, переходим к установке прекомпилированного пакета клиентской части MySQL:

# pkg_add /usr/ports/packages/i386/all/mysql-client-5.0.22.tgz

Уделяем внимание зависимостям mysql-server'а:

# cd /usr/ports/databases/p5-DBD-mysql
# make install clean CLEANDEPENDS=Yes

И устанавливаем пакадж серверной части MySQL:

# pkg_add /usr/ports/packages/i386/all/mysql-server-5.0.22.tgz

При необходимости создаем директорию /var/mysql:

# mkdir -p /var/mysql
# chown _mysql:_mysql /var/mysql

Настало время проверить работоспособность БД и запустить скрипт для создания типовых баз mysql и test:

# /usr/local/bin/mysql_install_db

Теперь в стартовом сценарии /etc/rc.local указываем опции для mysqld_safe - своего рода обертки, которая запускает mysqld с заданными параметрами, производит мониторинг состояния демона и при необходимости перезапускает главный процесс MySQL.

# vi /etc/rc.local

if [ -x /usr/local/bin/mysqld_safe ]; then
echo -n ' mysqld'
/usr/local/bin/mysqld_safe --user=_mysql \
--open-files=1000 --skip-networking \
--socket=/var/www/var/run/mysql/mysql.sock &
fi

Прокомментирую опции, которые мы указали при старте MySQL:

- --USER=_MYSQL - ЗАПУСК ДЕМОНА ОТ ИМЕНИ НЕПРИВИЛЕГИРОВАННОГО ПОЛЬЗОВАТЕЛЯ _MYSQL;
- --OPEN-FILES=1000 - МАКСИМАЛЬНОЕ ЧИСЛО ОТКРЫТЫХ ФАЙЛОВ;
- --SKIP-NETWORKING - MYSQLD НЕ ДОЛЖЕН БИНДИТЬСЯ НА СЕТЕВЫЕ АДРЕСА;
- --SOCKET=/VAR/WWW/VAR/RUN/MYSQL/MYSQL.SOCK - ТАК КАК НАША БД БУДЕТ ИСПОЛЬЗОВАТЬСЯ ТОЛЬКО ЛОКАЛЬНО УСТАНОВЛЕННЫМИ ПРОГРАММАМИ, РАБОТАЕМ ЧЕРЕЗ СОКЕТ;
- '&' - ВЫПОЛНЯЕМ ПЕРЕВОД MYSQLD_SAFE В ФОНОВЫЙ РЕЖИМ.

Чтобы не изобретать велосипед, давай возьмем предлагаемый разработчиками пример конфига MySQL, назначим ему корректные права доступа и отредактируем применительно к нашим задачам:

# cp /usr/local/share/mysql/my-medium.cnf /etc/my.cnf
# chmod 644 /etc/my.cnf
# vi /etc/my.cnf
 
[client]
socket = /var/www/var/run/mysql/mysql.sock
 
[mysqld]
socket = /var/www/var/run/mysql/mysql.sock
skip-locking
key_buffer = 16M
max_allowed_packet = 1M
table_cache = 64
sort_buffer_size = 512K
net_buffer_length = 8K
myisam_sort_buffer_size = 8M
 
[mysqldump]
quick
max_allowed_packet = 16M
 
[mysql]
no-auto-rehash

Как ты мог заметить, главное отличие от дефолтного my-medium.cnf заключается в определении местоположения абсолютного пути до сокета клиента и сервера MySQL. Вместо /var/run/mysql/mysql.sock мы будем использовать /var/www/var/run/mysql/mysql.sock, поэтому своевременно подготавливаем соответствующую поддиректорию:

# mkdir -p /var/www/var/run/mysql
# chown _mysql:_mysql /var/www/var/run/mysql

Для хранения временных файлов необходимо создать каталог /var/www/tmp с либеральными правами доступа:

# mkdir -p -m 777 /var/www/tmp

С установкой и конфигурированием разобрались, переходим к запуску демона на орбиту:

# /usr/local/bin/mysqld_safe --user=_mysql --open-files=1000 \
--skip-networking --socket=/var/www/var/run/mysql/mysql.sock &
 
Проверяем, готов ли mysqld принимать входящие подключения:

# fstat | grep mysql

_mysql mysqld 22841 wd /var/mysql 2 drwxr-xr-x r 1024
_mysql mysqld 22841 0 / 67197 crw-rw-rw- r null
_mysql mysqld 22841 1 /var/mysql 3 -rw-rw---- w 25648
_mysql mysqld 22841 2 /var/mysql 3 -rw-rw---- w 25648
_mysql mysqld 22841 3 pipe 0xd69e8828 state

И создаем (для надежности) символическую ссылку на стандартное расположение сокета:

# ln -sf /var/www/var/run/mysql/mysql.sock /var/run/mysql/mysql.sock

нardening MySQL в подробностях

Опциональный шаг: выполняем ряд несложных операций по увеличению безопасности MySQL:

# /usr/local/bin/mysql -u root

// Пустой пароль для администратора MySQL-сервера нам не подходит, устанавливаем новый
mysql> set password for root@localhost=password("noidea");
 
// Удаляем базу данных test, которая была создана скриптом mysql_install_db
mysql> drop database test;
 
// Удаляем все MySQL'ные учетные записи, кроме root
mysql> use mysql;
mysql> delete from db;
mysql> delete from user where not (host="localhost" and user="root");
mysql> flush privileges;
 
// Чтобы усложнить атаки типа bruteforce, можно изменить имя главной учетной записи с root на admin
mysql> update user set user="admin" where user="root";
mysql> flush privileges;
 
// Настройка закончена
mysql> quit

хардкорные разборки с PHP

Далее на очереди - PHP4 со своими расширениями. Следующими командами мы установим пакет с основным движком - так называемый core-пакадж, модуль для работы с базами данных и библиотеку pear (набор специальных компонентов и расширений для PHP).

# pkg_add php4-core-4.4.1p0.tgz
# pkg_add php4-mysql-4.4.1p0.tgz
# pkg_add php4-pear-4.4.1p0.tgz

Активируем модуль libphp4.so:

# /usr/local/sbin/phpxs -s

Воспользуемся рекомендованной разработчиками версией php.ini:

# cp /usr/local/share/examples/php4/php.ini-recommended /var/www/conf/php.ini

Выставляем корректные права доступа:

# chown root:www /var/www/conf/php.ini
# chmod 640 /var/www/conf/php.ini

Указываем путь до сокета MySQL:

# vi /var/www/conf/php.ini

mysql.default_socket = /var/run/mysql/mysql.sock

И активируем MySQL-модуль:

# /usr/local/sbin/phpxs -a mysql

сам себе надежный почтальон

Для корректной работы электронной почты в Apache chroot необходимо установить статически слинкованную версию mini_sendmail. Этот фэйковый почтовик будет передавать из среды chroot всю исходящую почту полноценному транспортному агенту.

# cd /usr/port/mail/mini_sendmail
# env SUBPACKAGE=-chroot make install
# cp -p /bin/sh /var/www/bin
# mkdir -p /var/www/etc
# cp /etc/{hosts,resolv.conf} /var/www/etc

Теперь снова возвращаемся в php.ini и указываем абсолютный путь до mini_sendmail относительно /var/www (внимание: запись «-fwww@mydomain.ru» обязательно должна идти без пробела).

# vi /var/www/conf/php.ini

sendmail_path = "/bin/mini_sendmail -fwww@mydomain.ru -t"

не выпускай суккуба из песочницы

Разработчики OpenBSD выполнили львиную долю работы за нас, посадив Apache/mod_ssl в chroot-окружение. Нам лишь остается активировать поддержку PHP и разобраться с виртуальными хостами. Для этого переходим к редактированию главного конфигурационного файла индейца:

# vi /var/www/conf/httpd.conf

// Подгружаем модуль PHP4
LoadModule php4_module /usr/lib/apache/modules/libphp4.so
 
// Добавляем PHP'шные классы к типу MIME
<IfModule mod_php4.c>
AddType application/x-httpd-php .php .php4
AddType application/x-httpd-php-source .phps
</IfModule>
 
// Расширяем список файлов, которые при WWW-запросе будут обрабатываться в первую очередь
DirectoryIndex index.html index.php index.php4
 
// Указываем виртуальные интерфейсы (в данном случае используется виртуальный хостинг на основе имен)
NameVirtualHost 192.168.1.1
NameVirtualHost 192.168.3.1
NameVirtualHost 212.XX.XY.162
 
// Внутри контейнера VirtualHost задаем параметры конфигурации для www.mydomain.ru
<VirtualHost 192.168.1.1 192.168.3.1 212.XX.XY.162>
ServerAdmin admin@mydomain.ru
DocumentRoot /var/www/virtual/www.mydomain.ru
ServerName www.mydomain.ru
ServerAlias mydomain.ru
ErrorLog logs/virtual.www.mydomain.ru-error_log
CustomLog logs/virtual.www.mydomain.ru-access_log common
</VirtualHost>
 
// Определяем списки контроля доступа для директории с файлами, предназначенными только для администрирования CMS
<Directory "/var/www/virtual/www.mydomain.ru/admin">
Order deny,allow
Deny from all
Allow from localhost 192.168.1.0/24 192.168.3.0/24 212.XX.XY.162
</Directory>

управляем MySQL с комфортом

PHPMyAdmin представляет собой набор PHP-скриптов для управления сервером MySQL. Прекрасно подходит для поклонников визуального администрирования и тех, у кого синтаксис SQL-запросов вызывает определенную сложность. Кроме того, с помощью PHPMyAdmin довольно удобно выполнять рутинные операции по бэкапу, созданию и модификации баз данных, таблиц, пользователей и т.д. Устанавливаем:

# tar zxvf phpMyAdmin-2.8.2.tar.gz
# mkdir -p /var/www/virtual
# cp -Rp phpMyAdmin-2.8.2 /var/www/virtual/phpmyadmin.mydomain.ru
# cd /var/www/virtual/phpmyadmin.mydomain.ru
# cp libraries/config.default.php config.inc.php

В конфиге config.inc.php указываем, что в качестве типа соединения у нас используется «сокет» (напомню, mysqld не подвешен даже на интерфейс обратной петли), а также имя и пароль администратора MySQL:

# vi config.inc.php

$cfg['Servers'][$i]['socket'] = '';
$cfg['Servers'][$i]['connect_type'] = 'socket';
$cfg['Servers'][$i]['auth_type'] = 'config';
$cfg['Servers'][$i]['user'] = 'admin';
$cfg['Servers'][$i]['password'] = 'noidea';

Описание поддомена phpmyadmin.mydomain.ru в httpd.conf будет выглядеть следующим образом:

# vi /var/www/conf/httpd.conf

<VirtualHost 192.168.1.1 192.168.3.1>
ServerAdmin admin@mydomain.ru
DocumentRoot /var/www/virtual/phpmyadmin.mydomain.ru
ServerName phpmyadmin.mydomain.ru
ErrorLog logs/virtual.phpmyadmin.mydomain-error_log
CustomLog logs/virtual.phpmyadmin.mydomain-access_log common
</VirtualHost>

Совершенно очевидно, что доступ к phpMyAdmin необходимо ограничить. Этого можно добиться разными способами. Для расширения кругозора предлагаю воспользоваться аутентификацией по паролю. Чтобы проконтролировать доступ к каталогу /var/www/virtual/phpmyadmin.mydomain.ru и запретить по сети передавать пароли в открытом виде (директива SSLRequireSSL), создаем еще один управляющий файл - .htaccess. Преимущество использования такого подхода состоит в том, что мы не захламляем httpd.conf дополнительными директивами для описания правил доступа, указания местонахождения Auth-конфигов и методов аутентификации. Плюс к этому, при изменении конфигурации в файле .htaccess не придется перезагружать Web-сервер.

# vi /var/www/virtual/phpmyadmin.mydomain.ru/.htaccess

SSLRequireSSL
AuthType Basic
AuthName "Password Required"
AuthUserFile /var/www/conf/.htpasswd
AuthGroupFile /dev/null
<Limit GET POST>
require user admin
</Limit>

Аутентификационную базу /var/www/conf/.htpasswd (ни в коем случае не размещай .htpasswd в каталоге /var/www/virtual/phpmyadmin.mydomain.ru) будем вести с помощью утилиты htpasswd(1). Ключ '-c' отвечает за создание базы, ключ '-m' задает использование алгоритма шифрования MD5, вместо применяемой по умолчанию DES'овской функции crypt(3):

# htpasswd -cm /var/www/conf/.htpasswd admin

Только суперпользователь и демон httpd имеют право обращаться к базе с паролями:

# chown root:www /var/www/conf/.htpasswd
# chmod 640 /var/www/conf/.htpasswd

проводим безопасные транзакции по протоколу https

Чтобы получить возможность устанавливать защищенные сеансы по протоколу https, необходимо создать приватный ключ, ввести регистрационные данные и подписать сертификат собственным ключом. Начнем с генерации секретного RSA-ключа длиной 1024 бит:

# openssl genrsa -out /etc/ssl/private/server.key 1024

Создаем запрос на сертификат:

# openssl req -new -key /etc/ssl/private/server.key \

-out /etc/ssl/private/server.csr
Country Name (2 letter code) []:RU
State or Province Name (full name) []:Russia
Locality Name (eg, city) []:Moscow
Organization Name (eg, company) []:MySite
Organizational Unit Name (eg, section) []:<Enter>
Common Name (eg, fully qualified host name) []:www.mydomain.ru
Email Address []:admin@mydomain.ru
A challenge password []:<Enter>
An optional company name []:<Enter>

Подписываем сертификат, который будет действовать на протяжении 10 лет (аргумент '-days 3650'), своим ключом:

# openssl x509 -req -days 3650 -in /etc/ssl/private/server.csr \

-signkey /etc/ssl/private/server.key -out /etc/ssl/server.crt

Выполняем остановку и повторный запуск httpd(8), но уже с поддержкой https:

# apachectl stop
# apachectl startssl

Проверяем, забиндился ли апач на соответствующие порты:

% netstat -na -f inet | egrep '80|443'

tcp 0 0 *.80 *.* LISTEN
tcp 0 0 *.443 *.* LISTEN

В /etc/pf.conf создаем правило, разрешающее прохождение запросов к портам 80 и 443:

# vi /etc/pf.conf

$ext_if = "fxp0"
pass in log on $ext_if inet proto tcp from any to $ext_if \
port { www, https } flags S/SA keep state

Чтобы внесенные изменения вступили в силу, не забудь перезагрузить набор рулесетов файервола:

# pfctl -f /etc/pf.conf

В конфиге /etc/rc.conf следующими записями разрешаем автоматическую загрузку Apache SSL и Packet Filter при старте системы:

# vi /etc/rc.conf

httpd_flags="-DSSL"
pf=YES

постскриптумы

На этом настройку можно считать завершенной. Протестировать работу модуля php4 и его взаимодействие с MySQL можно с помощью php-файла, исходный код которого приведен ниже. Если при запросе www.mydomain.ru/test.php ты получишь лаконичный ответ «ok», смело начинай заливать любимую CMS'ку в каталог /var/www/virtual/www.mydomain.ru. Удачи.

# vi /var/www/virtual/www.mydomain.ru/test.php

<html><body>
<?php
mysql_connect("localhost", "admin", "noidea") or die("failed");
print "ok";
mysql_close();
?>
</body></html>


Источник: http://www.xakep.ru/magazine/xs/069/050/1.asp
Категория: Apache | Добавил: oleg (08.03.2008) | Автор: ANDREY MATVEEV
Просмотров: 1275 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Форма входа

Beastie

Друзья сайта

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
links

Copyright MyCorp © 2024