На 25-ом уроке мы переходим к одной из важных тем в веб-разработке, это безопасность. Если до этого мы учились создавать функциональные приложения, то сейчас научимся защищать их от злоумышленников. Безопасность это не «опциональная фича», а обязательный слой вашего кода. Даже небольшая ошибка может привести к утечке данных, взлому сайта или потере доверия пользователей. В этом уроке разберем основные принципы безопасности, а также научимся защищаться от XSS и CSRF-атак.
Перед тем как углубляться в конкретные уязвимости, давайте обсудим общие правила, которые должен соблюдать каждый разработчик.
Валидация это проверка, что данные соответствуют ожидаемому формату (например, email содержит символ @). Санитизация это очистка данных от опасных символов или преобразование их в безопасный формат.
Пример:
// Валидация email $email = $_POST['email']; if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { die("Некорректный email!"); } // Санитизация строки $username = $_POST['username']; $clean_username = htmlspecialchars($username, ENT_QUOTES, 'UTF-8');
Правило:
filter_var(), htmlspecialchars(), strip_tags().SQL-инъекции это атаки, когда злоумышленник внедряет вредоносный SQL-код через поля ввода (например, формы логина).
Как защищаться:
Пример с PDO:
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'password'); $stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email'); $stmt->execute(['email' => $email]); $user = $stmt->fetch();
Никогда не делайте так:
// Уязвимый код! $sql = "SELECT * FROM users WHERE email = '$email'"; $result = mysqli_query($conn, $sql);
Все современные сайты должны работать по протоколу HTTPS. Он шифрует данные между клиентом и сервером, защищая их от перехвата.
Как внедрить:
.htaccess:apache
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Хранить пароли в открытом виде это преступление. Используйте функции хеширования:
// Хеширование пароля $password = 'user_password_123'; $hash = password_hash($password, PASSWORD_DEFAULT); // Проверка пароля if (password_verify($password, $hash)) { echo 'Пароль верный!'; }
Устаревшие версии PHP, библиотек или CMS (например, WordPress) содержат уязвимости. Регулярно обновляйте все компоненты вашего проекта.
Настройте права доступа к файлам и базам данных так, чтобы у пользователей и скриптов были только необходимые привилегии. Например, скрипт для выборки данных из БД не должен иметь прав на удаление таблиц.
XSS это уязвимость, позволяющая злоумышленнику внедрить вредоносный JavaScript-код на страницу вашего сайта. Это может привести к краже куки-файлов, перенаправлению пользователей на фишинговые сайты или подмене контента.
Пример уязвимого кода:
// Уязвимый код: выводим данные без обработки echo $_GET['search_query'];
Если злоумышленник передаст в search_query строку <script>alert('XSS!');</script>, на странице выполнится JavaScript.
Все данные, выводимые в HTML, должны быть обработаны функцией htmlspecialchars().
Пример:
$user_comment = $_POST['comment']; // Очищаем данные перед выводом echo htmlspecialchars($user_comment, ENT_QUOTES, 'UTF-8');
CSP позволяет ограничить источники скриптов, стилей и других ресурсов.
Пример заголовка:
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'");
Удаляйте опасные теги и атрибуты с помощью strip_tags() или библиотек вроде HTML Purifier.
Пример:
$user_bio = $_POST['bio']; // Разрешаем только теги <b>, <i>, <p> $clean_bio = strip_tags($user_bio, '<b><i><p>');
Условие:
Создайте форму для комментариев, где пользователь вводит имя и текст. Защитите форму от XSS.
Решение:
<?php if ($_SERVER['REQUEST_METHOD'] === 'POST') { $name = htmlspecialchars($_POST['name'], ENT_QUOTES, 'UTF-8'); $comment = htmlspecialchars($_POST['comment'], ENT_QUOTES, 'UTF-8'); // Сохраняем в базу данных или выводим echo "<div class='comment'><strong>$name</strong>: $comment</div>"; } ?> <form method="POST"> <input type="text" name="name" placeholder="Ваше имя"> <textarea name="comment" placeholder="Ваш комментарий"></textarea> <button type="submit">Отправить</button> </form>
CSRF это атака, когда злоумышленник заставляет пользователя выполнить нежелательное действие на сайте, где он авторизован. Например, изменить пароль или сделать перевод денег.
Сценарий атаки:
example.com.example.com/change-password.example.com не защищен от CSRF, запрос выполнится от имени пользователя.Идея: генерировать уникальный токен для каждой формы и проверять его при отправке.
Шаги:
Пример:
session_start();
// Генерация токена
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
// Форма
<form method="POST">
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
<!-- Остальные поля -->
</form>
// Проверка токена
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die('Неверный CSRF-токен!');
}
Проверяйте, что запрос пришел с вашего домена:
if (!isset($_SERVER['HTTP_REFERER']) || parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) !== 'yourdomain.com') { die('Недействительный источник запроса!'); }
Но учтите: Заголовок Referer может отсутствовать или быть подделанным. Используйте этот метод только как дополнение к CSRF-токенам.
Условие:
Создайте форму для изменения пароля с CSRF-защитой.
Решение:
<?php session_start(); // Генерация токена if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } if ($_SERVER['REQUEST_METHOD'] === 'POST') { // Проверка токена if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) { die('Ошибка CSRF!'); } // Обработка данных $new_password = $_POST['new_password']; // ... смена пароля ... echo 'Пароль успешно изменен!'; } ?> <form method="POST"> <input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>"> <input type="password" name="new_password" placeholder="Новый пароль"> <button type="submit">Сменить пароль</button> </form>
Сегодня мы разобрали ключевые аспекты безопасности в PHP:
Безопасность это процесс, а не разовое действие. Всегда тестируйте свой код, используйте инструменты вроде OWASP ZAP для поиска уязвимостей и следите за обновлениями.
Хотите узнать больше? Переходите к следующим урокам: полный курс по PHP для начинающих. Там мы разберем работу с базами данных, авторизацию и создание REST API!