Статья

Лучшие практики безопасности PHP 🔒

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

Разберём, как защитить свой PHP-проект: от простых привычек до продвинутых настроек сервера. Всё по делу, без заумных терминов.


1. Проверяй и фильтруй все входные данные

Самая частая ошибка новичков — доверять тому, что приходит от пользователя. Любая форма, запрос, cookie или даже URL могут содержать вредный код.

Что делать:

  • Всегда проверяй тип данных. Если ожидаешь число — убедись, что это число.

  • Для строк используй filter_var() или htmlspecialchars().

  • Для e-mail — filter_var($email, FILTER_VALIDATE_EMAIL);

  • Для URL — filter_var($url, FILTER_VALIDATE_URL).

Пример:

$name = htmlspecialchars($_POST['name'], ENT_QUOTES, 'UTF-8');

Так ты превращаешь любые HTML-теги в безопасный текст, и злоумышленник не сможет внедрить JavaScript в страницу.


2. Не вставляй переменные напрямую в SQL-запросы

SQL-инъекция — классика. Хакер может ввести в форму «' OR 1=1 --» и получить доступ ко всей базе данных.

Неправильно:

$query = "SELECT * FROM users WHERE email = '$_POST[email]'";

Правильно:

$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$_POST['email']]);

Используй подготовленные запросы (prepared statements) с PDO или mysqli.


3. Хешируй пароли правильно

Хранить пароли в открытом виде — преступление. Даже md5() или sha1() — уже прошлый век. Современные алгоритмы хеширования не просто шифруют, а добавляют «соль» и адаптивную сложность.

Используй:

$hash = password_hash($password, PASSWORD_DEFAULT);
if (password_verify($password, $hash)) {
    // вход разрешён
}

PASSWORD_DEFAULT автоматически выбирает лучший алгоритм (сейчас это bcrypt или argon2).


4. Отключи вывод ошибок в продакшне

Если сайт показывает пользователю ошибки PHP — это подарок для хакера. Там может быть путь к файлам, конфигурации и SQL-запросы.

В продакшне:

display_errors = Off
log_errors = On
error_log = /var/log/php_errors.log

Ошибки логируй в файл, но не показывай на экране.


5. Используй HTTPS везде

Без HTTPS данные, отправленные формой, могут быть перехвачены. SSL-сертификат сейчас можно получить бесплатно, например, через Let’s Encrypt.

В .htaccess добавь:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

И в коде:

if (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off') {
    header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
    exit;
}

6. Не используй eval(), exec() и подобные функции

eval() выполняет код как PHP. Это очень опасно: если туда попадёт хоть кусочек пользовательских данных, сайт можно полностью взломать.

Запомни:

  • eval() — зло.

  • shell_exec(), system(), passthru() — тоже под запретом.

  • include и require должны использовать жёстко прописанные пути, а не переменные от пользователя.


7. Скрывай структуру проекта

Не позволяй пользователям видеть, что у тебя внутри.

Советы:

  • Удали файл phpinfo.php после настройки.

  • Закрой доступ к .git/, vendor/, config/.

  • В папках без index.php создай пустой index.html, чтобы не показывался список файлов.


8. Используй session_regenerate_id()

Когда пользователь входит в систему, PHP создаёт сессию. Но если злоумышленник перехватит session_id, он сможет войти под чужим логином.

Решение:

session_start();
session_regenerate_id(true);

Так создаётся новый идентификатор, и старый теряет силу.


9. Храни конфиги вне публичной папки

Файл config.php с паролем от базы не должен лежать в /public_html или /www. Лучше вынести его на уровень выше.

Например:

/var/www/project/config.php
/var/www/project/public/index.php

В index.php:

require __DIR__ . '/../config.php';

Так даже если кто-то доберётся до веб-директории, конфиг останется недоступен.


10. Проверяй загрузку файлов

Если пользователь может загружать файлы, это огромная дыра. Он может закинуть .php-файл и запустить его на сервере.

Что делать:

  • Разрешай только нужные форматы (jpg, png, pdf).

  • Проверяй MIME-тип через finfo_file().

  • Меняй имя файла на случайное.

  • Храни файлы вне папки, где выполняется PHP.

Пример:

$target = '/uploads/' . uniqid() . '.jpg';
move_uploaded_file($_FILES['file']['tmp_name'], $target);

11. Используй Content Security Policy (CSP)

CSP помогает защититься от XSS (внедрения скриптов). Она указывает браузеру, откуда можно загружать контент.

В заголовках ответа добавь:

header("Content-Security-Policy: default-src 'self'; script-src 'self'");

Теперь никакие сторонние скрипты не запустятся без разрешения.


12. Защита от CSRF

CSRF (Cross-Site Request Forgery) — это когда кто-то заставляет браузер отправить запрос от твоего имени. Например, ссылку на удаление аккаунта.

Как защититься:

  • Генерируй CSRF-токен в сессии.

  • Добавляй его в форму как скрытое поле.

  • Проверяй при отправке.

Пример:

// при показе формы
$_SESSION['csrf'] = bin2hex(random_bytes(32));
echo '<input type="hidden" name="csrf" value="' . $_SESSION['csrf'] . '">';

// при обработке
if (!hash_equals($_SESSION['csrf'], $_POST['csrf'])) {
    die('CSRF detected');
}

13. Обновляй PHP и библиотеки

Много дыр появляется не в твоём коде, а в старых версиях PHP или фреймворков.

Периодически делай:

php -v
composer update

Переходи на актуальные ветки (PHP 8.3 и выше). В старых версиях уже не закрывают уязвимости.


14. Ограничь права файлов и папок

Минимум прав — максимум безопасности.

Рекомендации:

  • Файлы: 644

  • Папки: 755

  • Конфиги: 600

  • Владелец — пользователь, от имени которого работает веб-сервер.

И не давай права 777, если не хочешь сюрпризов.


15. Используй disable_functions в php.ini

Можно отключить опасные функции прямо в настройках PHP.

Пример:

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

Это особенно важно, если у тебя shared-хостинг.


16. Правильно работай с заголовками

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

header("X-Frame-Options: DENY");
header("X-Content-Type-Options: nosniff");
header("Referrer-Policy: no-referrer-when-downgrade");
header("Permissions-Policy: geolocation=(), microphone=()");

Они закрывают уязвимости, связанные с фреймами, подменой MIME-типа и сбором данных.


17. Не доверяй $_SERVER и $_REQUEST

Многие разработчики берут данные из $_SERVER['HTTP_REFERER'] или $_REQUEST. Но их легко подделать.

Лучше всегда использовать чёткие источники:

  • $_POST для форм;

  • $_GET для URL;

  • $_COOKIE для куков.

И не полагайся на HTTP_REFERER при проверке логики.


18. Проверяй длину входных данных

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

Пример:

if (strlen($_POST['username']) > 50) {
    die('Too long');
}

19. Ставь лимиты на запросы (rate limiting)

Чтобы защититься от брутфорса, можно ограничить число попыток входа.

Простая идея:

  • Считай попытки входа по IP в Redis или базе.

  • Если больше 5 за минуту — блокируй временно.

Есть готовые решения — reCAPTCHA, RateLimiter, Laravel Throttle.


20. Не забывай про бэкапы

Без резервных копий никакая безопасность не спасёт. Делай автоматические бэкапы базы и файлов хотя бы раз в день.

Проверяй, можно ли их восстановить — просто хранить архивы бесполезно, если они битые.


21. Мониторь логи и активность

Настрой логирование входов, ошибок, подозрительных действий. Можно писать всё в syslog или использовать инструменты вроде Fail2Ban, Wazuh, Elastic Stack.

Иногда можно поймать взломщика по странным IP или попыткам входа ночью.


22. Используй фреймворки с защитой из коробки

Если пишешь на чистом PHP — ты сам отвечаешь за всё. Но современные фреймворки (Laravel, Symfony, Yii) уже включают:

  • CSRF-защиту,

  • фильтрацию ввода,

  • безопасную ORM,

  • XSS-фильтры.

Это не отменяет осторожности, но снимает много рутины.


23. Не доверяй сторонним библиотекам

Перед установкой пакета из Composer глянь:

  • когда он обновлялся;

  • кто автор;

  • есть ли подозрительные зависимости.

Вредоносные пакеты уже не редкость.


24. Используй WAF (Web Application Firewall)

Если у тебя крупный проект, поставь WAF — например, ModSecurity. Он фильтрует запросы и блокирует подозрительные.

На облачных сервисах типа Cloudflare можно включить защиту без настройки сервера.


25. Думай как хакер

Проверяй свой код глазами злоумышленника.

Попробуй:

  • Ввести в поля кавычки, скобки, теги;

  • Изменить куки;

  • Открыть URL с параметрами вручную;

  • Загрузить файл с расширением .php.

Если где-то сработало — исправь.


Итог

Безопасность — не галочка в чеклисте, а привычка. Нужно не просто поставить защиту один раз, а думать о ней на каждом этапе: от написания кода до деплоя.

PHP — мощный инструмент, но как и любой инструмент, он опасен в неумелых руках.

Если относиться к безопасности всерьёз, твой сайт будет стоять годами, не боясь ни SQL-инъекций, ни XSS, ни CSRF. И тогда можно спокойно спать, зная, что система держится крепко. 💪

Для ответа вы можете авторизоваться