Запрет доступа PHP: настройки безопасности и права

Раздел: Администрирование PHP -> Безопасность и права доступа

Основное решение: комплексная блокировка PHP через конфигурацию веб-сервера и PHP

Как полностью запретить выполнение PHP-скриптов в определённых директориях?

Наиболее эффективный способ - отключить обработку PHP-файлов на уровне веб-сервера. Для Apache используется директива FilesMatch в .htaccess или в конфигурации виртуального хоста:


<FilesMatch \.php$>
    Order Deny,Allow
    Deny from all
</FilesMatch>
  

Php доступ запрещен (запрет доступа php)

Для Nginx аналогичный эффект достигается исключением PHP-файлов из обработки FastCGI:


location ~ \.php$ {
    deny all;
}
  

Эти правила полностью блокируют доступ к любым PHP-скриптам в заданном каталоге. Сервер вернёт ошибку 403 Forbidden при попытке открыть *.php.

Проблема: если в каталоге лежат статические файлы (CSS, JS), то они не пострадают. Но если требуется разрешить доступ к некоторым PHP-скриптам (например, index.php), но запретить остальные, нужно использовать более тонкую настройку - например, разрешить только конкретные имена.


<FilesMatch "^(index|config)\.php$">
    Order Allow,Deny
    Allow from all
</FilesMatch>
<FilesMatch "\.php$">
    Order Deny,Allow
    Deny from all
</FilesMatch>
    

Ошибка: если не указать порядок обработки, правила могут конфликтовать. Рекомендуется проверять порядок FilesMatch - сначала разрешающие, потом запрещающие.

Варианты решений и их цели

Как ограничить доступ к PHP через директивы open_basedir?

Директива open_basedir ограничивает файловые операции PHP только указанными директориями. Это предотвращает чтение и запись за пределами разрешённой области.


; php.ini или .user.ini (для каталога)
open_basedir = "/var/www/site:/tmp"
  

Цель: если злоумышленник загрузит PHP-шелл, он не сможет получить доступ к системным файлам (например, /etc/passwd).

Типичная ошибка: указание путей с завершающим слешом и без - для open_basedir слеш не требуется. Нельзя использовать символы подстановки, только точные пути. При указании нескольких путей в Windows разделитель ;, в Unix - :.

Как отключить опасные функции через disable_functions?

В php.ini можно задать список функций, которые не должны выполняться ни в одном скрипте.


disable_functions = exec, system, shell_exec, passthru, popen, proc_open, curl_exec, curl_multi_exec, parse_ini_file, show_source, highlight_file
  

Цель: предотвратить выполнение команд ОС, сокетов и других потенциально опасных операций.

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

Дополнительный нюанс: некоторые функции (например, exec) могут быть переопределены через расширения. disable_functions не блокирует функции, вызванные через отражение (ReflectionFunction).

Как запретить выполнение PHP в определённых директориях через .htaccess с AddHandler?

Один из популярных методов - удалить ассоциацию расширения .php с обработчиком PHP для конкретной папки:


RemoveHandler .php
RemoveType .php
  

После этого Apache перестанет передавать PHP-файлы интерпретатору, и они будут отдаваться как обычный текст (или скачиваться).

Важно: если используется FastCGI или php-fpm, директивы RemoveHandler могут не сработать. В таких случаях применяют блокировку через FilesMatch.

Как изолировать выполнение PHP через chroot или контейнеры?

Для глубокой изоляции можно настроить PHP-FPM с опцией chroot. Скрипт будет видеть только корневую файловую систему, заданную в конфигурации пула.


; pool.d/example.conf
[example]
chroot = /var/www/chroot
  

Цель: полная изоляция - даже если злоумышленник выполнит код, он не выйдет за пределы chroot-окружения.

Сложность: нужно скопировать все необходимые системные файлы (библиотеки, устройства) в chroot-каталог. Малейшая ошибка приведёт к неработоспособности приложения. В современных сценариях чаще используют Docker.

Как ограничить доступ PHP к файловой системе через PHP_INI_SYSTEM директивы?

Некоторые параметры, такие как allow_url_fopen и allow_url_include, могут быть отключены, чтобы предотвратить удалённые включения файлов.


allow_url_fopen = Off
allow_url_include = Off
  

Цель: предотвратить RFI- и LFI-атаки.

Проблема: отключение allow_url_fopen может нарушить работу легитимных функций, таких как file_get_contents('https://...'). Нужно оценить необходимость.

Как запретить загрузку PHP-файлов через веб-интерфейс?

В конфигурации сервера можно установить размер загружаемых файлов и типы. Для Apache в .htaccess:


php_value upload_max_filesize 2M
php_value post_max_size 3M
php_value max_execution_time 30
  

Но это не блокирует загрузку PHP-сценариев. Лучше комбинировать с проверкой MIME-типа в приложении.

Расширенные примеры и результаты

Пример 1: Блокировка PHP только для определённых расширений (кроме .php7, .phtml)

Пример

# .htaccess
<FilesMatch "\.(php|phtml|php3|php4|php5|php7|phps)$">
    Order Deny,Allow
    Deny from all
</FilesMatch>

Результат: любой запрос к файлам с указанными расширениями вернёт 403. Если нужно разрешить, например, .php7, его нужно исключить из шаблона.

Пример 2: Использование PHP-опции auto_prepend_file для блокировки

Можно определить скрипт, который будет выполняться перед каждым PHP-запросом и проверять, разрешена ли директория:

Пример

; php.ini или .user.ini
auto_prepend_file = /var/www/block.php

Содержимое block.php:

Пример

<?php
$restricted_dirs = ['/var/www/uploads', '/var/www/cache'];
$script_dir = dirname($_SERVER['SCRIPT_FILENAME']);
foreach ($restricted_dirs as $dir) {
    if (strpos($script_dir, $dir) === 0) {
        http_response_code(403);
        die('Access denied');
    }
}
Результат: при попытке выполнить скрипт из /var/www/uploads/test.php браузер получит 403 Forbidden.

Пример 3: Блокировка PHP через расширение Suhosin

Suhosin - патч для PHP с дополнительными возможностями блокировки. Пример конфигурации:

Пример

; php.ini
extension=suhosin.so
suhosin.executor.func.blacklist = "exec,system,passthru"
suhosin.executor.eval.blacklist = "include,require"
suhosin.mail.protect = 2

Результат: вызов указанных функций завершится ошибкой, даже если они не указаны в disable_functions. Также Suhosin добавляет защиту от атак типа null byte.

Пример 4: Запрет доступа к PHP через Nginx с проверкой IP

Разрешить выполнение PHP только для определённых IP-адресов администраторов:

Пример

location ~ \.php$ {
    allow 192.168.1.0/24;
    allow 10.0.0.1;
    deny all;
    include fastcgi_params;
    fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
Результат: PHP-скрипты выполняются только для пользователей из указанных подсетей. Остальные получают 403.

Пример 5: Блокировка PHP с помощью PHP-расширения disable_classes

Можно полностью запретить использование определённых классов (например, для отключения доступа к PDO):

Пример

; php.ini
disable_classes = "PDO,PDOStatement,ReflectionClass"

Результат: любой код, пытающийся создать экземпляр PDO, вызовет фатальную ошибку.

Пример 6: Ограничение доступа через .user.ini в подкаталогах

Создайте файл .user.ini в каталоге /var/www/private:

Пример

; /var/www/private/.user.ini
open_basedir = "/var/www/private"
disable_functions = exec, system, ini_set
Результат: все PHP-скрипты внутри private будут видеть только свою директорию и не смогут менять настройки через ini_set.

Пример 7: Комплексная блокировка через mod_rewrite в Apache

Перенаправлять все запросы к .php на статическую страницу, но разрешить только index.php:

Пример

RewriteEngine On
RewriteCond %{REQUEST_URI} \.php$
RewriteCond %{REQUEST_URI} !^/index\.php$
RewriteRule .* /forbidden.html [R=403,L]

Результат: любой запрос к любому PHP-файлу, кроме index.php, будет перенаправлен на 403.

Пример 8: Использование PHP-FPM pool с ограничениями

В конфигурации пула PHP-FPM можно установить лимиты на ресурсы и заблокировать некоторые функции через php_admin_value:

Пример

[secured]
user = www-data
group = www-data
pm = dynamic
pm.max_children = 5
php_admin_value[disable_functions] = exec,system
php_admin_value[open_basedir] = /var/www/secured
Результат: все скрипты в этом пуле работают с ограниченными правами, не могут выполнять системные команды и видят только свою директорию.

Пример 9: Блокировка через .htaccess с использованием mod_authz_core (Apache 2.4+)

Пример

<FilesMatch \.php$>
    Require all denied
</FilesMatch>

Результат: все PHP-файлы закрыты. Чтобы открыть конкретный файл, используйте <Files "file.php"> Require all granted </Files>.

Пример 10: Проверка конфигурации после изменений

Для проверки, какие директивы включены, создайте скрипт info.php с phpinfo() и временно разместите в тестовом каталоге. После тестов удалите.

Пример

<?php phpinfo(); ?>

Посмотрите раздел Configuration File (php.ini) Path и disable_functions.

Запрет доступа PHP - comments

En
Php доступ запрещен (php)