Статья

Лучшие практики безопасности PHP: полный гид для разработчиков 🔒🐘

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

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


1. Фильтрация и валидация входных данных

Основной источник уязвимостей — неконтролируемые данные, поступающие от пользователей.

1.1 Валидируйте все данные

  • Проверяйте email:
$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
if (!$email) die("Неверный email");
  • Проверяйте URL:
$url = filter_var($_POST['url'], FILTER_VALIDATE_URL);
  • Для чисел используйте:
$age = filter_var($_POST['age'], FILTER_VALIDATE_INT, ["options" => ["min_range"=>1, "max_range"=>120]]);

1.2 Ограничивайте длину и символы

$name = trim($_POST['name']);
if (!ctype_alpha(str_replace(' ', '', $name)) || strlen($name) > 50) {
    die("Недопустимое имя");
}

1.3 Регулярные выражения

Регулярки позволяют проверять специфические форматы, например телефон:

$phone = preg_match('/^\+7\d{10}$/', $_POST['phone']);

2. Подготовленные выражения и безопасная работа с базой

SQL-инъекции — самая распространённая угроза.

2.1 MySQLi

$stmt = $mysqli->prepare("SELECT * FROM users WHERE email=?");
$stmt->bind_param("s", $email);
$stmt->execute();

2.2 PDO

$stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (:name, :email)");
$stmt->execute(['name'=>$name, 'email'=>$email]);

Подготовленные выражения автоматически экранируют пользовательские данные, предотвращая внедрение SQL-кода.


3. Экранирование вывода данных

Чтобы предотвратить XSS (внедрение скриптов), нельзя выводить пользовательский ввод напрямую:

echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
  • Используйте htmlspecialchars() для HTML.

  • Для атрибутов, URL и JS применяйте отдельные фильтры.


4. Защита загрузки файлов

Файлы — источник уязвимостей, если не контролировать их тип, размер и место хранения.

4.1 Основные правила

  • Проверяйте MIME-тип:
$allowed = ['image/jpeg','image/png'];
$mime = mime_content_type($_FILES['file']['tmp_name']);
if (!in_array($mime, $allowed)) die("Неподдерживаемый формат");
  • Ограничивайте размер:
if ($_FILES['file']['size'] > 2*1024*1024) die("Файл слишком большой");
  • Храните файлы за пределами веб-доступа.

  • Генерируйте уникальные имена файлов:

$fileName = time().'_'.basename($_FILES['file']['name']);

5. Безопасные сессии

Сессии хранят данные пользователей, и их нужно защищать:

session_start();
session_regenerate_id(true);
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1); // только для HTTPS
  • Храните сессии вне общедоступного каталога.

  • Ограничивайте время жизни сессии.


6. Пароли и аутентификация

  • Хэшируйте пароли:
$hash = password_hash($password, PASSWORD_DEFAULT);
  • Проверка:
if(password_verify($input, $hash)) { /* авторизация */ }
  • Не храните пароли в открытом виде.

  • Применяйте сложные пароли и двухфакторную аутентификацию для админки.


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

  • Защищайте конфигурационные файлы .php с помощью .htaccess.

  • Не размещайте критически важные файлы в веб-каталоге.

  • Настройте права:

chmod 644 config.php
chmod 755 /uploads

8. Защита от CSRF

Cross-Site Request Forgery позволяет злоумышленнику выполнять действия от имени пользователя.

8.1 Токены CSRF

// Генерация токена
$_SESSION['token'] = bin2hex(random_bytes(32));

// В форме
<input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">

// Проверка
if (!hash_equals($_SESSION['token'], $_POST['token'])) die('CSRF защита сработала');

9. Логи и мониторинг

  • Не показывайте ошибки пользователю на продакшене:
ini_set('display_errors', 0);
ini_set('log_errors', 1);
error_log('Ошибка: ...');
  • Анализируйте логи для выявления подозрительной активности.

10. Настройка сервера и PHP

  • Используйте актуальную версию PHP.

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

disable_functions = exec,passthru,shell_exec,system
  • Ограничьте доступ PHP к файловой системе: open_basedir.

  • Используйте HTTPS и включите HSTS.


11. Защита от атак на форму

  • Ограничивайте частоту отправки (rate limiting).

  • Применяйте CAPTCHA или honeypot.

  • Проверяйте тип и размер загружаемых файлов.

  • Экранируйте данные перед выводом и отправкой по почте.


12. Дополнительные рекомендации

  • Минимизируйте вывод ошибок на продакшене.

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

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

  • Регулярно обновляйте PHP, CMS и библиотеки.


13. Примеры реальных атак и защита

13.1 XSS

Проблема: пользователь вставляет <script> в комментарий.

Решение:

echo htmlspecialchars($comment, ENT_QUOTES, 'UTF-8');

13.2 SQL-инъекция

Проблема: пользователь вводит ' OR '1'='1 в форму логина.

Решение: подготовленные выражения:

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

13.3 CSRF

Проблема: злоумышленник отправляет форму от имени пользователя.

Решение: токен CSRF.


14. Итог

Сайт на PHP безопасен, если:

  1. Валидируются и фильтруются все данные.

  2. Используются подготовленные выражения для SQL.

  3. Экранируется вывод данных.

  4. Защищены файлы и сессии.

  5. Пароли хранятся только в хэшированном виде.

  6. Формы защищены от CSRF и ботов.

  7. Сервер настроен безопасно и используется HTTPS.

  8. Логи ведутся и анализируются.

  9. Применяются регулярные обновления PHP, CMS и библиотек.

Следуя этим практикам, вы создадите устойчивый к атакам и безопасный сайт, который защищает данные пользователей и ваш бизнес.

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