Представьте, что вы построили дом. Красивый, уютный, с новенькой мебелью. Но забыли закрыть окна и двери. Рано или поздно кто-то зайдет и унесет самое ценное. Так и с PHP-приложением. Можно написать крутой функционал, но если не думать о безопасности, данные пользователей могут уплыть к злоумышленникам. Эта статья — про то, как закрыть те самые «окна» и «двери» в вашем коде. Без паники, только практика.
1. SQL-инъекции: как злоумышленники крадут базу данных
SQL-инъекция — это когда хакер вставляет в запрос свой SQL-код через поля ввода. Например, в форме логина вместо имени пользователя он вводит что-то вроде admin' OR '1'='1. Если вы просто вставляете переменные в запрос, база данных может выполнить этот код и отдать все данные.
Как защититься? Используйте подготовленные запросы (prepared statements). Они отделяют данные от кода. Вот пример на PHP с PDO:
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute(['email' => $_POST['email']]);
$user = $stmt->fetch();Видите? Вместо того чтобы вставлять $_POST['email'] прямо в строку, мы используем плейсхолдер :email. PDO сам экранирует данные. Это просто и надежно.
2. XSS-атаки: когда скрипты выполняются на вашем сайте
XSS (Cross-Site Scripting) — это когда злоумышленник внедряет JavaScript-код в страницу. Например, через комментарий или поле ввода. Этот код может украсть куки, перенаправить пользователя на фишинговый сайт или изменить содержимое страницы.
Основная защита — экранирование вывода. В PHP есть функция htmlspecialchars(). Она превращает специальные символы в безопасные HTML-сущности. Пример:
$comment = $_POST['comment'];
echo htmlspecialchars($comment, ENT_QUOTES, 'UTF-8');Если пользователь введет <script>alert('XSS')</script>, на экране появится просто текст, а не выполнится скрипт. Для контекста JavaScript (например, в атрибутах) используйте дополнительные проверки.
| Тип XSS | Описание | Защита |
|---|---|---|
| Отраженный (Reflected) | Код передается через URL или форму и сразу отображается | Экранирование вывода, валидация ввода |
| Хранимый (Stored) | Код сохраняется в базе данных (например, в комментариях) | Экранирование при выводе, Content Security Policy |
| DOM-based | Код выполняется через изменение DOM на клиенте | Избегать опасных JS-методов (innerHTML) |
3. CSRF: как защититься от поддельных запросов
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-атака обнаружена');
}Токен должен быть уникальным для каждой сессии или формы. Не храните его в куках.
4. Управление сессиями и безопасность паролей
Сессии хранят данные пользователя на сервере. Если злоумышленник украдет ID сессии, он сможет войти под чужим аккаунтом. Поэтому:
- Используйте HTTPS, чтобы трафик был зашифрован.
- Устанавливайте флаг HttpOnly для кук сессии (чтобы JavaScript не мог их прочитать).
- Регулярно обновляйте ID сессии после входа (session_regenerate_id()).
Пароли — это отдельная песня. Никогда не храните их в открытом виде. Используйте функцию password_hash() и password_verify(). Пример:
// Хеширование пароля при регистрации
$hash = password_hash($password, PASSWORD_BCRYPT);
// Проверка при входе
if (password_verify($input_password, $hash)) {
echo 'Пароль верный';
}Bcrypt — это медленный алгоритм, что усложняет подбор паролей. Не используйте md5 или sha1 — они слишком быстрые.
5. Дополнительные меры: валидация, настройки сервера и обновления
Валидация — это проверка данных на стороне сервера. Например, если ожидается email, используйте filter_var($_POST['email'], FILTER_VALIDATE_EMAIL). Не доверяйте клиентской проверке.
Настройки сервера тоже важны:
- Отключите display_errors в production, чтобы не светить пути к файлам.
- Установите правильные права на файлы (например, 644 для файлов, 755 для директорий).
- Используйте open_basedir для ограничения доступа к файловой системе.
И самое главное — обновляйте PHP и библиотеки. Разработчики постоянно исправляют уязвимости. Не будьте тем, кто использует PHP 5.6 в 2025 году.
Что в итоге?
Безопасность PHP-приложений — это не магия, а набор простых привычек. Используйте подготовленные запросы, экранируйте вывод, внедряйте CSRF-токены, правильно храните пароли и обновляйте зависимости. Начните с малого — хотя бы с одного пункта из этой статьи. Ваши пользователи скажут спасибо. А хакеры пойдут искать другую цель.



