Как защитить PHP-приложения от киберугроз: практическое руководство
PHP остается одним из самых популярных языков для веб-разработки, но его гибкость и доступность делают его частой мишенью для хакеров. Рассказываем, как защитить ваше приложение от основных угроз.
1. Борьба с SQL-инъекциями
Угроза: Внедрение вредоносного SQL-кода через параметры запросов.
Решение:
- Используйте подготовленные выражения (PDO):
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute(['email' => $_POST['email']]);
$user = $stmt->fetch();
- Никогда не вставляйте данные напрямую в запрос:
// Опасный код!
$query = "SELECT * FROM users WHERE id = " . $_GET['id'];
2. Защита от XSS (Межсайтовый скриптинг)
Угроза: Внедрение JavaScript-кода через пользовательский ввод.
Решение:
- Экранируйте вывод данных:
echo htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
- Используйте шаблонизаторы (Twig, Blade):
{{ user_input|escape }}
3. Предотвращение CSRF-атак
Угроза: Подделка межсайтовых запросов для выполнения действий от имени пользователя.
Решение:
- Генерируйте CSRF-токены:
session_start();
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
- Проверяйте токен в формах:
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die("Invalid CSRF token");
}
4. Безопасная работа с сессиями
Угроза: Перехват сессионных кук.
Решение:
- Настройте параметры кук:
session_set_cookie_params([
'lifetime' => 3600,
'path' => '/',
'secure' => true, // Только HTTPS
'httponly' => true, // Запрет доступа через JS
'samesite' => 'Strict'
]);
session_start();
- Регенерируйте ID сессии после входа:
session_regenerate_id(true);
5. Защита файловых загрузок
Угроза: Загрузка вредоносных файлов.
Решение:
- Проверяйте MIME-тип и расширение:
$allowed = ['image/jpeg', 'image/png'];
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['file']['tmp_name']);
if (!in_array($mime, $allowed)) {
die("Invalid file type");
}
- Сохраняйте файлы вне корневой директории:
move_uploaded_file($_FILES['file']['tmp_name'], '/var/private_uploads/file.jpg');
6. Валидация входных данных
Угроза: Непредсказуемое поведение из-за некорректных данных.
Решение:
- Используйте фильтры:
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
- Белый список для критичных операций:
$allowedActions = ['view', 'edit', 'delete'];
if (!in_array($_GET['action'], $allowedActions)) {
die("Invalid action");
}
7. Настройки сервера и PHP
Угроза: Утечка информации через ошибки.
Решение:
- Отключите вывод ошибок в production:
ini_set('display_errors', '0');
error_reporting(0);
- Обновляйте PHP: Устаревшие версии (PHP 5.x, 7.0) не получают обновлений безопасности.
8. HTTPS и заголовки безопасности
Угроза: Перехват данных и атаки типа «человек посередине».
Решение:
- Принудительный HTTPS:
if ($_SERVER['HTTPS'] !== 'on') {
header("Location: https://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
exit();
}
- Установите security-заголовки:
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: DENY');
header('Content-Security-Policy: default-src \'self\'');
9. Защита от брутфорса
Угроза: Множественные попытки подбора пароля.
Решение:
- Ограничьте попытки входа:
if ($_SESSION['login_attempts'] > 5) {
die("Try again in 15 minutes");
}
- Используйте CAPTCHA:
if (!verifyRecaptcha($_POST['g-recaptcha-response'])) {
die("CAPTCHA failed");
}
10. Резервное копирование и мониторинг
Угроза: Потеря данных и скрытые атаки.
Решение:
- Настройте ежедневные бэкапы:
# Пример cron-задачи
0 3 * * * mysqldump -u user -p dbname > /backups/db.sql
- Анализируйте логи:
tail -f /var/log/apache2/error.log | grep 'POST /login'
Заключение
Безопасность PHP-приложения — это непрерывный процесс. Ключевые шаги:
- Всегда санируйте входные и выходные данные.
- Никогда не доверяйте пользовательскому вводу.
- Регулярно обновляйте зависимости и сам PHP.
- Используйте многоуровневую защиту (WAF, HTTPS, брандмауэр).
Помните: 100% защиты не существует, но грамотная настройка снизит риски на порядок. Тестируйте приложение через инструменты вроде OWASP ZAP и проводите аудиты безопасности.