Директива open_basedir: управление доступом к файлам

Раздел: Администрирование PHP -> Настройки PHP

Директива open_basedir в PHP

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

Пример настройки в php.ini:

open_basedir = "/var/www/site1:/tmp:/usr/share/php"

Php open basedir (директива open_basedir в php)

После изменения файла требуется перезапустить веб-сервер или PHP-FPM. Данный подход работает на всех серверных моделях (mod_php, CGI, FastCGI).

Цели использования: изоляция сайтов друг от друга, предотвращение чтения системных файлов (паролей, конфигураций), защита от атак с включением локальных файлов (LFI).

Типичная ошибка: Warning: file_exists(): open_basedir restriction in effect. File(/etc/passwd) is not within the allowed path(s). Решение: добавить нужную директорию в список или изменить путь в скрипте.

Нельзя изменить через ini_set(): директива имеет режим PHP_INI_SYSTEM, поэтому её можно задать только в php.ini, .htaccess (если разрешено) или конфигурации пула FPM.

Как ограничить доступ для одного сайта через .htaccess?

Если на сервере включена директива AllowOverride Options или AllowOverride All, можно задать php_value open_basedir в файле .htaccess в корне сайта.

php_value open_basedir "/home/user/www:/tmp"

Php max vars (максимальное количество переменных в php (max_input_vars))

Проблема: при использовании Apache mod_php директива работает, но для CGI/FastCGI может потребоваться .user.ini. Если нет прав на перезагрузку сервера, этот метод самый удобный.

Ошибка 500 Internal Server Error может возникнуть, если синтаксис неверен (лишние кавычки, пробелы). Проверить конфигурацию можно командой apachectl -t.

Как настроить open_basedir в пуле PHP-FPM?

Для каждого пула FPM (например, для конкретного сайта) можно задать директиву в файле php-fpm.d/www.conf или pool.d/site.conf.

php_admin_value[open_basedir] = /var/www/site2:/tmp

Php max execution (максимальное время выполнения скрипта в php (max_execution_time))

Преимущество: переопределение невозможно из скрипта, так как php_admin_value имеет более высокий приоритет.

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

Как использовать .user.ini для ограничения в CGI/FastCGI?

В каталоге веб-приложения можно создать файл .user.ini (не путать с .htaccess). Он действует только для PHP CGI/FastCGI.

open_basedir = "/var/www/html:/tmp"

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

Не работает с mod_php: .user.ini игнорируется в режиме модуля Apache. Решение: использовать .htaccess или php.ini.

Расширенные примеры работы с open_basedir. Все примеры выполняются на Linux.

Пример 1: Проверка текущего значения из скрипта

Пример
echo 'Open basedir: ' . ini_get('open_basedir');
Open basedir: /var/www/html:/tmp

Если директива не задана, вернётся пустая строка. Это полезно для отладки.

Пример 2: Обработка ошибки open_basedir

Пример
$file = '/etc/passwd';
if (file_exists($file)) {
    echo 'Файл существует';
} else {
    echo 'Файл не найден или доступ запрещён';
}

Результат: предупреждение и возврат false (если отключено подавление ошибок). В production скрипт может продолжать работу, но рекомендуется проверять ошибки с помощью set_error_handler.

Пример
set_error_handler(function($severity, $message, $file, $line) {
    if (stripos($message, 'open_basedir restriction') !== false) {
        throw new RuntimeException('Доступ к файлу запрещён');
    }
    return false;
});
try {
    $content = file_get_contents('/etc/passwd');
} catch (RuntimeException $e) {
    echo $e->getMessage();
}
Доступ к файлу запрещён

Пример 3: Настройка через конфигурацию Apache (VirtualHost)

Внутри блока <VirtualHost> или <Directory>:

Пример
<Directory /var/www/site3>
    php_value open_basedir "/var/www/site3:/tmp:/var/www/site3/cache"
</Directory>

Этот способ удобен, если на одном сервере несколько сайтов, каждый со своей изоляцией. Требуется перезагрузка Apache.

Пример 4: Запрет на выполнение файлов из определённой папки (сочетание с disable_functions)

Директива open_basedir не ограничивает выполнение скриптов через include, если сам скрипт находится в разрешённой папке. Для дополнительной защиты комбинируют с disable_functions.

Пример
disable_functions = exec, system, shell_exec, passthru, popen, proc_open

Пример конфигурации для разделения прав:

Пример
[PHP]
open_basedir = /home/user/public_html:/tmp
disable_functions = exec, system, popen

Пример 5: Использование open_basedir с символическими ссылками

Директива разрешает доступ по реальному пути, а не по ссылке. Если в корне сайта есть симлинк на папку вне разрешённой зоны, доступ к ней будет запрещён.

Пример
ln -s /etc/ /var/www/html/secret_config
Пример
file_get_contents('/var/www/html/secret_config/passwd'); // ошибка
Warning: file_get_contents(): open_basedir restriction in effect...

Решение: добавить реальный путь /etc в список open_basedir, если это необходимо для работы приложения.

Директива open_basedir в PHP - comments

En
Php open basedir (php)