+7(904)3314610

О безопасной структуре каталогов и организации библиотек в связке apache php MySQL

moveinfo.ru

баннер статьи

Дата:

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

Некоторые настройки сервера и структура каталогов

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

Физическая структура каталогов при такой организации может быть следующей:

  • /home/user/ – домашний каталог user;
  • /home/user/httpdoc/ – верхний каталог доступный для скриптов php запущенных пользователем user;
  • /home/user/httpdoc/www/ – каталог виртуального хоста www.example.ru (песочница виртуального хоста);
  • /home/user/httpdoc/www/public/ – песочница клиента сделавшего запрос на www.example.ru;
  • /home/user/httpdoc/www/public/cgi-bin/ – каталог доступных к исполнению программ для клиента.

##############################################################
# файл конфигурации виртуальных хостов
##############################################################
# общие настройки для всех хостов пользователя user
# ip адрес на котором расположены виртуальные хосты например:
NameVirtualHost 192.168.0.100

# index-ный файл(ы) по умолчанию в директориях, к ним происходит
# обращение клиента по умолчанию привелегии по порядку следования в строке)
DirectoryIndex index.html index.php index.htm index.xhtml default.htm default.html

# Права доступа к директории и её наследникам  ⁄home⁄user⁄httpdoc
<Directory ⁄home⁄user⁄httpdoc>
  # настройка песочницы php
  # php не может обращаться к каким либо файлам выше указанной директории
  # это очень важный параметр безопастности
  php_admin_value open_basedir ⁄home⁄user⁄httpdoc
  # игнорируем файлы .htaccess
  # AllowOverride None
  # запрещаем вывод содержимого директорий при отсутствии index
  Options -Indexes
  # запрещаем доступ всем
  Order allow,deny
  Deny from all
<⁄Directory>

##############################################################
# индивидуальная настройка хостов пользователя user
##############################################################
# для www.example.ru
<VirtualHost 192.168.0.100>
  ServerAdmin webmaster@example.ru
  ServerName www.example.ru
  DocumentRoot ⁄home⁄user⁄httpdoc⁄www⁄public
  # Права доступа к директории ⁄home⁄user⁄httpdoc⁄www⁄
  <Directory ⁄home⁄user⁄httpdoc⁄www⁄>
    # игнорируем файлы .htaccess
    AllowOverride None
    # запрещаем вывод содержимого директорий при отсутствии index
    Options -Indexes
    # запрещаем доступ всем
    Order allow,deny
    Deny from all
  <⁄Directory>
  # Права доступа к директории ⁄home⁄user⁄httpdoc⁄www⁄public⁄
  <Directory ⁄home⁄user⁄httpdoc⁄www⁄public⁄>
    # разрешаем доступ всем
    Order deny,allow
    Allow from all
    # кодировка HTTP заголовков
    AddDefaultCharset UTF-8
    # разрешаем перенаправление
    RewriteEngine on
    # если нет физического файла или директория
    RewriteCond %{SCRIPT_FILENAME} !-f
    RewriteCond %{SCRIPT_FILENAME} !-d
    # перенаправляем
    RewriteRule ^(.*)$ index.php [L]
  <⁄Directory>
  # Права доступа к директории ⁄home⁄user⁄httpdoc⁄www⁄public⁄cgi-bin⁄
  ScriptAlias ⁄cgi-bin⁄ ⁄home⁄user⁄httpdoc⁄www⁄public⁄cgi-bin⁄
  <Directory ⁄home⁄user⁄httpdoc⁄www⁄public⁄cgi-bin⁄>
    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order deny,allow
    Allow from all
  <⁄Directory>
<⁄VirtualHost>
##############################################################
# для v1.example.ru
# .......
# .......
# .......
##############################################################
# для v2.example.ru
# .......
# .......
# ....... etc ...

Часть файла приведённого в (листинг 1) может быть размещена в файле .htaccess, такое решение обычно предлагают некоторые хостеры, по понятным причинам ограничения доступа клиентов к настройкам файлов apache. Практическое использование файлов .htaccess следует по возможности избегать, и вот по каким причинам. При использовании .htaccess настройки могут быть (а могут и не быть) разбросаны по различным каталогам при этом: происходит децентрализация управляющих структур, что усложняет их обслуживание и контроль; возрастает вероятность повреждения одного или нескольких файлов .htaccess; на чтение каждого файла необходимо дополнительное время, т.е. возрастает расход времени причём на самых медленных машинных операциях (обращении к данным на внешних носителях); и самое главное файлы .htaccess могут находится в области доступа внешних клиентов. Таким образом, настройки доступа и переадресации (по возможности) лучше располагать вместе с настройками хостов или виртуальных хостов. Обычно эти файлы (OS Debian, Ubuntu и некоторых других из семейства Linux) расположены в каталогах:

  • /etc/apache2/sites-available/ – все хосты;
  • /etc/apache2/sites-enabled/ – доступные хосты (здесь обычно хранятся ссылки на некоторые хосты из /etc/apache2/sites-available/).

После организации системы каталогов на сервере можно перейти к организации системы каталогов приложения, в нашем случае программы на php. Рассмотренная структура каталогов позволяет сделать файлы библиотеки программ недоступными для внешних клиентов и при этом доступных для пользователя user и инициированных им процессов. Структура каталогов может быть, например, следующая:

недоступные внешнему клиенту:

  • /home/user/httpdoc/www/lib/php – библиотека php;
  • /home/user/httpdoc/www/lib/bash – библиотека bash;
  • /home/user/httpdoc/www/lib/perl – библиотека perl;
  • /home/user/httpdoc/www/log – каталог лог-файлов;
  • /home/user/httpdoc/www/setting – настройки;
  • /home/user/httpdoc/www/data – данные;
  • и т.д.

доступные внешнему клиенту:

  • /home/user/httpdoc/www/public/ – всё что в этом каталоге (если в настройках не указанно иначе);
  • /home/user/httpdoc/www/public/image – изображения;
  • /home/user/httpdoc/www/public/js – JS файлы;
  • /home/user/httpdoc/www/public/css – CSS файлы;
  • /home/user/httpdoc/www/public/swf – SWF файлы;
  • и т.д.

Таким образом, области доступа разделены и не пересекаются не на физическом (уровень каталогов) не на логическом (уровень предикатов доступа) уровнях. Разработчики многих CMS (Content Management System – система управления содержимым) не могут себе позволить разделить физически пространство расположения файлов, программ и библиотек от области доступной внешнему клиенту. Это связано с тем, что их системы предназначены, в том числе, для использования на хостах с ограниченным доступом пользователей к настройкам сервера. В таких случаях имеется возможность лишь логического разделения при помощи файлов .htaccess, что как мы уже обсуждали, не является лучшим решением с точки зрения безопасности. Разработчикам CMS для ограничения доступа к исполняемым файлам, в целях безопасности, дополнительно приходится прибегать к различным уловкам, например, в начале каждого файла ставить проверку условия значения или существования некоторой переменной, которая в свою очередь задаётся в файле обеспечивающим санкционированный доступ. Если переменная не обнаружена или её значение не соответствует условию, происходит выход. Например, файл index.php (листинг 2)


<?php
// задаём значение позволяющее сделать проверку корректного входа
$GLOBALS['enter_test'] = 'secret_code';
// подключаем файл
include('performer.php');
// что-то дальше ...

// чистим память
unset($GLOBALS['enter_test']);
?>

Файл performer.php (листинг 3).


<?php
// если переменная $GLOBALS['enter_test'] не определена
// или её значение, или тип не соответствует контрольному, выходим.
if(!isset($GLOBALS['enter_test'])) exit;
if($GLOBALS['enter_test'] !=== 'secret_code') exit;

// иначе что-то делаем ...
?>

Управление подпрограммами

В соответствии с рассмотренной концепцией все элементы, расположенные в каталоге /home/user/httpdoc/www/public/ являются точками доступа. Точками доступа могут быть не только файлы, которые клиент видит как *.php, *.html, *.xml и т.д., но и файлы которые пользователь видит как, например, изображения, pdf и пр. или вообще не видит, например, получает сообщение об ошибке. В качестве примера рассмотрим возможность доступа через индексный файл index.php (листинг 4). В файле index.php может быть реализован алгоритм управляющей модели приложения, поэтому целесообразным является разделение файла настроек (данных) и файла модели (управления). Подключение файла базовых настроек, осуществляется при помощи указания относительного пути (относительно файла index.php) (../setting/miconfig.php).


<?php
try {
  //=====================================================================
  // базовые настройки, задание конфигурации
  include_once('../setting/miconfig.php');

  //=====================================================================
  // подключение библиотек
  include_once('mibasic.php');    // библиотека базовых функций
  include_once('misqlquery.php'); // базовый клас MySQL


} catch( Exсeption $error ) {
  // обработчик исключения

}
?>

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


<?php
// настройки .....
// ещё настройки ....
// ещё .....
//=========================================================================
// определяем некоторые пути расположения библиотек
$sep = getenv('COMSPEC')?';':':'; // тип разделителя в зависимости от ОС
                                  // (в Windows и Linux различные разделители)
 ini_set( 'include_path', ini_get('include_path').$sep. // стандартный путь 
 getenv('DOCUMENT_ROOT').'/../setting'.$sep.            // настройки
 getenv('DOCUMENT_ROOT').'/../lib/php/function'.$sep.   // библиотеки функций
 getenv('DOCUMENT_ROOT').'/../lib/php/postgresql'.$sep. // библиотеки БД PostgreSQL
 getenv('DOCUMENT_ROOT').'/../lib/php/mysql'.$sep);     // библиотеки БД MySQL

//=========================================================================

// ещё настройки ....

?>

Формат указания путей (getenv('DOCUMENT_ROOT').'/../setting') или (getenv('DOCUMENT_ROOT').'/../lib/php/function') означает: подняться вверх на один уровень относительно корня, а корнем является (getenv('DOCUMENT_ROOT')) т.е. в рассматриваемом примере (/home/user/httpdoc/www/public/), и далее перейти по указанному адресу (setting) или (lib/php/function) соответственно. Можно прописывать абсолютный путь (например: /home/user/httpdoc/www/lib/php/function) но это уменьшит переносимость. Поиск подключаемых файлов осуществляется последовательно, начиная с каталога в котором расположен файл содержащий include_once() или include(), а затем в каталогах относительно корня указанных в переменной среды php - ('include_path'). Не следует задавать слишком большое число мест для поиска т.к. это может отрицательно сказаться на производительности.

Обратим внимание на приоритет использования директивы include_once() перед include(). Применение include_once() позволяет контролировать число подключений файлов (только 1 раз) исключая лишние расходы на загрузку и трансляцию файлов. Директива require() и require_once() в отличии от include() и include_once() требует обязательного присутствия подключаемого файла иначе выполнение сценария завершается.

Заключение

Рассмотрены некоторые структурные принципы модели организации файлов и библиотек php работающих в составе клиент-серверного приложения. На базе модели возможно синтезировать самые различные приложения. Основным достоинством является защищённость скриптов от несанкционированного доступа, обеспечивающая хорошее структурирование в соответствии с распространённой сегодня концепцией Модель-Вид-Контроллер (MVC, model-view-controller). Для организации php библиотек, работающих в составе программ запускаемых без сервера, так же можно использовать подобную структуру.

Литература

  1. The PHP Group. www.php.net
  2. The Apache Software Foundation. www.apache.org
  3. Григин И.Е. PHP руководство программиста (+CD). - СПб.: Питер, 2006. - 490 с.:ил.