Cross-Site Scripting (XSS): векторы атак и защита

Security2026-09-13TryQuickToolBox

Почему XSS до сих пор преследует веб-приложения

Межсайтовый скриптинг (XSS) остаётся одной из самых распространённых веб-уязвимостей. Несмотря на широкую осведомлённость, он неизменно присутствует в OWASP Top 10. Корень проблемы: приложения доверяют пользовательскому вводу и отображают его без должной обработки. Злоумышленники внедряют вредоносные скрипты, которые выполняются в браузерах жертв, что приводит к перехвату сессий, краже данных и дефейсу.

В этой статье разбираются векторы XSS-атак и предлагаются практические меры защиты, которые можно внедрить уже сегодня.

Что такое XSS и как это работает?

XSS возникает, когда приложение включает недоверенные данные в веб-страницу без проверки или кодирования. Браузер затем выполняет внедрённый скрипт, как если бы он был частью легитимного сайта. Поскольку скрипт выполняется в контексте уязвимого сайта, он может получить доступ к cookie, локальному хранилищу и выполнять запросы от имени пользователя.

Рассмотрим простую страницу поиска, которая отражает запрос:

<?php echo 'You searched for: ' . $_GET['q']; ?>

Если злоумышленник создаст URL вида search.php?q=<script>alert('XSS')</script>, скрипт выполнится, когда жертва перейдёт по ссылке.

Три основных типа XSS

1. Отражённый XSS

Вредоносный скрипт является частью запроса (например, параметра URL) и немедленно отражается в ответе. Жертву нужно обманом заставить кликнуть по ссылке или отправить форму. Часто используется в фишинговых кампаниях.

2. Хранимый XSS

Скрипт постоянно хранится на сервере (например, в базе данных, поле комментария или профиле пользователя). Каждый посетитель заражённой страницы выполняет скрипт. Хранимый XSS опаснее, так как не требует никаких действий, кроме просмотра страницы.

3. DOM-based XSS

Уязвимость существует в клиентском JavaScript, который читает данные из недоверенного источника (например, location.hash) и записывает их в DOM без безопасной обработки. Сервер может никогда не увидеть вредоносную нагрузку.

document.getElementById('output').innerHTML = location.hash.substring(1);

Если хэш содержит <img src=x>, скрипт выполнится.

Распространённые векторы атак

Защита от XSS

1. Кодирование вывода (контекстное экранирование)

Кодируйте все недоверенные данные перед выводом в HTML, атрибуты, JavaScript, CSS или URL. Используйте кодирование, соответствующее контексту:

Большинство современных фреймворков (React, Angular, Vue) автоматически экранируют по умолчанию, но будьте осторожны при использовании dangerouslySetInnerHTML или аналогичных обходных путей.

2. Валидация и санитизация ввода

Проверяйте ввод на стороне сервера с помощью белых списков. Для форматированного текста используйте библиотеку вроде DOMPurify для санитизации HTML, удаляя опасные теги и атрибуты.

const clean = DOMPurify.sanitize(userInput);

Никогда не полагайтесь только на клиентскую валидацию.

3. Content Security Policy (CSP)

CSP — мощный механизм эшелонированной защиты. Он ограничивает источники исполняемых скриптов, встроенных скриптов и других ресурсов. Строгая CSP может заблокировать XSS, даже если внедрение произошло.

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; object-src 'none';

Избегайте unsafe-inline и unsafe-eval. Используйте nonce или хэши для легитимных встроенных скриптов.

4. Безопасные атрибуты cookie

Устанавливайте cookie с атрибутами HttpOnly (запрещает доступ из JavaScript) и Secure (только HTTPS). Это смягчает перехват сессий через XSS.

5. Используйте современные фреймворки и избегайте опасных API

Фреймворки вроде React, Angular и Vue автоматически экранируют данные. Избегайте прямого манипулирования DOM через innerHTML. Если необходимо вставить HTML, сначала санитизируйте его.

6. Регулярное тестирование безопасности

Внедрите SAST, DAST и ручное тестирование на проникновение. Инструменты вроде OWASP ZAP помогают выявлять XSS-уязвимости.

Сравнение типов XSS и основных мер защиты

Тип XSSОписаниеОсновная защита
ОтражённыйНагрузка в запросе, отражается в ответеКодирование вывода, валидация ввода
ХранимыйНагрузка хранится на сервере, отдаётся всем пользователямСанитизация, кодирование вывода, CSP
DOM-basedКлиентское внедрение через небезопасные DOM APIБезопасные DOM API, CSP, отказ от eval

Пошагово: внедрение защиты от XSS

  1. Определите все точки ввода: формы, параметры URL, заголовки, cookie.
  2. Примените контекстное кодирование вывода: используйте встроенные функции или библиотеки вроде OWASP Java Encoder.
  3. Санитизируйте форматированный текст: используйте DOMPurify или аналоги.
  4. Разверните CSP: начните с режима report-only, затем включите принудительно.
  5. Установите атрибуты HttpOnly и Secure для cookie.
  6. Обучайте разработчиков: тренируйте безопасным практикам кодирования.
  7. Тестируйте регулярно: интегрируйте тестирование безопасности в CI/CD.

FAQ

В чём разница между XSS и CSRF?

XSS выполняет вредоносные скрипты в браузере жертвы, а CSRF заставляет браузер отправлять несанкционированные запросы на сайт, где пользователь аутентифицирован. XSS можно использовать для обхода защит CSRF.

Может ли Content Security Policy полностью предотвратить XSS?

Нет, CSP — это мера эшелонированной защиты. Она значительно снижает риск, но не может заменить правильное кодирование вывода и валидацию ввода. Неправильно настроенная CSP может всё ещё допускать некоторые атаки.

Достаточно ли клиентской валидации для предотвращения XSS?

Нет. Клиентскую валидацию легко обойти. Всегда проверяйте и кодируйте на стороне сервера и рассматривайте все клиентские данные как недоверенные.

Заключение

XSS — это постоянная угроза, но с многоуровневой стратегией защиты — кодирование вывода, валидация ввода, CSP и безопасные cookie — вы можете эффективно её смягчить. Будьте бдительны, обновляйте фреймворки и тестируйте непрерывно.

Для дополнительных инструментов безопасности ознакомьтесь с нашим Nginx Log Analyzer для обнаружения подозрительных шаблонов в серверных логах.