К основному содержимому

PHP Security: усиление безопасности через настройки php.ini

PHP · 19.04.2026 · 4 мин чтения
Иллюстрация к статье «PHP Security: усиление безопасности через настройки php.ini»

Зачем хардить PHP

PHP имеет множество функций, опасных при неправильной конфигурации. Правильная настройка php.ini закрывает целые классы уязвимостей: удалённое выполнение кода (RCE), раскрытие информации о сервере, перебор файлов через open_basedir обходы. Это первый шаг защиты любого PHP-сервера.

Скрыть информацию о PHP

expose_php = Off
; Убирает заголовок X-Powered-By: PHP/8.x из HTTP-ответов

Отключить опасные функции

disable_functions = exec,passthru,shell_exec,system,proc_open,popen,\
    curl_exec,curl_multi_exec,parse_ini_file,show_source,\
    phpinfo,posix_kill,posix_mkfifo,posix_setpgid
Некоторые приложения (например, WP-CLI, Imagick) могут требовать часть этих функций. Проверьте после применения, что всё работает корректно.

Ограничение доступа к файловой системе

open_basedir = /var/www/mysite:/tmp:/usr/share/php
; Запрещает PHP читать файлы за пределами указанных директорий

Отключить удалённые URL

allow_url_fopen = Off
allow_url_include = Off
; Блокирует file_get_contents("http://...") и include с удалённых URL

Безопасные настройки сессий

session.cookie_httponly = On
session.cookie_secure = On
session.cookie_samesite = Strict
session.use_strict_mode = On
session.use_only_cookies = On
session.gc_maxlifetime = 1440

Настройки загрузки файлов

file_uploads = On
upload_tmp_dir = /tmp
upload_max_filesize = 64M
; Ограничьте upload_tmp_dir правами www-data

Отключить register_globals и magic_quotes (PHP < 5.4)

; Устаревшие, но проверьте в старых конфигах:
register_globals = Off
magic_quotes_gpc = Off

Чеклист безопасности PHP

  • expose_php = Off — скрыть версию PHP
  • display_errors = Off — не показывать ошибки пользователям
  • log_errors = On — логировать ошибки в файл
  • allow_url_include = Off — запретить удалённые include
  • disable_functions — отключить опасные функции
  • session.cookie_httponly = On — защита сессий
  • open_basedir — ограничить файловую систему
# Применить изменения
sudo systemctl reload php8.2-fpm

# Проверка
php -r "phpinfo();" 2>&1 | grep expose_php
Используйте PHP Security Checker: установите composer require enlightn/security-checker для автоматической проверки известных уязвимостей в зависимостях.

Реальные ошибки после хардинга

Функция отключена через disable_functions

Warning: shell_exec() has been disabled for security reasons in /var/www/html/deploy.php on line 22

Это предупреждение, а не фатальная ошибка: вызов молча возвращает NULL, выполнение скрипта продолжается. Код, не проверяющий результат shell_exec() на null, дальше падает уже с другой, менее понятной ошибкой — отладка усложняется вдвойне.

allow_url_fopen заблокировал запрос

Warning: file_get_contents(http://api.example.com/data): Failed to open stream: no suitable wrapper could be found in /var/www/html/app/Api.php on line 8

После allow_url_fopen = Off функции вроде file_get_contents() и fopen() перестают открывать сетевые адреса — это ожидаемо и правильно, но код, читающий внешние API через них, нужно переписать на cURL заранее, до выката хардинга на прод.

Нарушение open_basedir

Warning: file_get_contents(): open_basedir restriction in effect. File(/etc/passwd) is not within the allowed path(s): (/var/www/mysite:/tmp:/usr/share/php) in /var/www/mysite/app/Reader.php on line 5

Это ровно то поведение, ради которого директива и включалась — попытка выйти за пределы разрешённых путей блокируется ещё до системного вызова. Если легитимный код получает эту ошибку на путях, которые должны быть доступны, — расширьте список через двоеточие, а не отключайте директиву целиком.

Когда хардинг ломает легитимные инструменты

  • disable_functions с proc_open и popen ломает WP-CLI, деплой-скрипты через Composer scripts и любые инструменты, которые запускают внешние процессы — проверяйте список используемых утилит перед отключением.
  • Глобальный open_basedir ломает симлинки на общие библиотеки за пределами разрешённых путей — частая проблема при shared-vendor между несколькими проектами.
  • session.cookie_secure = On без HTTPS оставит пользователей без рабочих сессий вовсе — куки просто не будут отправляться браузером.

Проверка результата

# Версия PHP больше не палится в заголовках ответа
curl -I https://example.com | grep -i x-powered-by
# (пусто — значит expose_php сработал)

# Список фактически отключённых функций
php -i | grep disable_functions

# Проверка конкретной опасной функции из кода
php -r "var_dump(function_exists('exec'));"

Отсутствие заголовка X-Powered-By в ответе curl — надёжный признак, что expose_php = Off применился. Для проверки безопасной загрузки файлов дополнительно протестируйте реальную отправку файла через форму, а не только настройки php.ini.

Регулярно повторяйте эту проверку после каждого обновления PHP: новая минорная версия иногда возвращает директиву к значению по умолчанию, если она была задана только в отдельном модульном ini-файле, который апдейт пакета перезаписал.

Статья помогла?
← Назад в базу знаний Задать вопрос поддержке