Безопасность PHP приложений: топ-10 уязвимостей и методы защиты
PHP остается одним из самых популярных языков для веб-разработки, однако его гибкость часто оборачивается уязвимостями. По данным отчетов по безопасности, более 70% веб-приложений имеют хотя бы одну критическую уязвимость. В этой статье мы разберем топ-10 наиболее опасных уязвимостей PHP, приведем реальные примеры кода и покажем, как эффективно защитить ваше приложение.
1. SQL-инъекции (SQL Injection)
Самая распространенная и опасная уязвимость. Злоумышленник может внедрить произвольный SQL-код через пользовательский ввод.
Уязвимый код:
<?php
$id = $_GET['id'];
$query = "SELECT * FROM users WHERE id = $id";
$result = mysqli_query($conn, $query);
?>
Защита: использование подготовленных выражений (Prepared Statements):
<?php
$stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $_GET['id']);
$stmt->execute();
$result = $stmt->get_result();
?>
2. XSS (Cross-Site Scripting)
Внедрение вредоносных скриптов в веб-страницы. Бывает трех типов: отраженный, хранимый и DOM-based.
Уязвимый код:
<?php
echo "Привет, " . $_GET['name'];
?>
Защита: экранирование вывода:
<?php
echo "Привет, " . htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8');
?>
3. CSRF (Cross-Site Request Forgery)
Атака, при которой злоумышленник заставляет пользователя выполнить нежелательные действия на сайте, где он аутентифицирован.
Защита: использование CSRF-токенов:
<?php
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
// Проверка при отправке формы
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die('CSRF атака обнаружена!');
}
?>
<form method="POST">
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
<button type="submit">Отправить</button>
</form>
4. Path Traversal (Обход пути)
Уязвимость, позволяющая читать произвольные файлы на сервере.
Уязвимый код:
<?php
$file = $_GET['file'];
include("pages/" . $file);
?>
Защита: валидация и ограничение путей:
<?php
$allowed_files = ['about.php', 'contact.php', 'home.php'];
$file = basename($_GET['file']);
if (in_array($file, $allowed_files)) {
include("pages/" . $file);
} else {
die('Доступ запрещен');
}
?>
5. File Upload (Загрузка файлов)
Небезопасная загрузка файлов может привести к выполнению произвольного кода на сервере.
Защита: проверка MIME-типа и расширения:
<?php
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
$max_size = 5 * 1024 * 1024; // 5 MB
if ($_FILES['file']['size'] > $max_size) {
die('Файл слишком большой');
}
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $_FILES['file']['tmp_name']);
if (!in_array($mime_type, $allowed_types)) {
die('Недопустимый тип файла');
}
// Переименовываем файл для безопасности
$extension = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
$new_name = md5(uniqid()) . '.' . $extension;
move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $new_name);
?>
6. Session Fixation (Фиксация сессии)
Атака, при которой злоумышленник навязывает пользователю известный идентификатор сессии.
Защита: регенерация ID сессии:
<?php
session_start();
// После успешной аутентификации
if ($login_success) {
session_regenerate_id(true);
$_SESSION['user_id'] = $user['id'];
}
?>
7. Command Injection (Инъекция команд)
Выполнение произвольных системных команд через пользовательский ввод.
Уязвимый код:
<?php
$output = shell_exec("ping " . $_GET['ip']);
?>
Защита: экранирование и валидация:
<?php
$ip = filter_var($_GET['ip'], FILTER_VALIDATE_IP);
if ($ip === false) {
die('Некорректный IP-адрес');
}
$output = shell_exec("ping -c 1 " . escapeshellarg($ip));
?>
8. Insecure Deserialization (Небезопасная десериализация)
Атака на объекты PHP, позволяющая выполнить произвольный код.
Уязвимый код:
<?php
$data = unserialize($_COOKIE['user_data']);
?>
Защита: использование JSON вместо сериализации:
<?php
$data = json_decode($_COOKIE['user_data'], true);
if ($data === null && json_last_error() !== JSON_ERROR_NONE) {
die('Некорректные данные');
}
?>
9. LDAP Injection
Внедрение в LDAP-запросы, часто используется в корпоративных приложениях.
Защита: экранирование LDAP-спецсимволов:
<?php
function ldap_escape($str) {
$search = ['\\', '*', '(', ')', "\0"];
$replace = ['\5c', '\2a',