Лучшие практики безопасности PHP: полный гид для разработчиков 🔒🐘
- 1. Фильтрация и валидация входных данных
- 2. Подготовленные выражения и безопасная работа с базой
- 3. Экранирование вывода данных
- 4. Защита загрузки файлов
- 5. Безопасные сессии
- 6. Пароли и аутентификация
- 7. Ограничение доступа к файлам и папкам
- 8. Защита от CSRF
- 9. Логи и мониторинг
- 10. Настройка сервера и PHP
- 11. Защита от атак на форму
- 12. Дополнительные рекомендации
- 13. Примеры реальных атак и защита
- 14. Итог
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 безопасен, если:
-
Валидируются и фильтруются все данные.
-
Используются подготовленные выражения для SQL.
-
Экранируется вывод данных.
-
Защищены файлы и сессии.
-
Пароли хранятся только в хэшированном виде.
-
Формы защищены от CSRF и ботов.
-
Сервер настроен безопасно и используется HTTPS.
-
Логи ведутся и анализируются.
-
Применяются регулярные обновления PHP, CMS и библиотек.
Следуя этим практикам, вы создадите устойчивый к атакам и безопасный сайт, который защищает данные пользователей и ваш бизнес.