Приятно вспоминать невзгоды, если они миловали (Цицерон).

XSS

XSS (Cross-Site Scripting, межсайтовый скриптинг) — это класс уязвимостей веб-приложений, при котором злоумышленник добивается выполнения своего кода в браузере пользователя в контексте доверенного сайта. Основная проблема возникает тогда, когда приложение принимает данные, контролируемые пользователем, а затем помещает их в HTML-документ или DOM таким способом, который позволяет браузеру интерпретировать их как исполняемый код.

Название XSS исторически связано с идеей выполнения скрипта в контексте другого сайта, однако современное понятие значительно шире. Уязвимость может использоваться не только для кражи данных. В зависимости от приложения XSS позволяет изменять содержимое страницы, выполнять действия от имени пользователя, отправлять запросы с его полномочиями, получать доступ к данным, доступным JavaScript, и подменять отображаемую информацию. MDN отмечает, что успешная XSS-атака фактически позволяет внедрённому коду действовать так, как мог бы действовать собственный клиентский код сайта.

Как возникает XSS

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

Например, сайт может получать имя пользователя из формы и вставлять его непосредственно в HTML. Если приложение рассматривает полученную строку как готовую разметку, браузер уже не воспринимает её только как текст. В определённых обстоятельствах часть строки может стать HTML-элементом, атрибутом или JavaScript-кодом.

Упрощённая схема возникновения XSS выглядит следующим образом:

  1. пользовательский ввод поступает на сайт;
  2. приложение сохраняет его или сразу использует в ответе;
  3. данные попадают в HTML или DOM без необходимого экранирования либо санитизации;
  4. браузер интерпретирует полученное содержимое;
  5. внедрённый код выполняется в контексте уязвимого сайта.

Почему XSS опасна

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

В зависимости от архитектуры приложения XSS может позволить злоумышленнику:

  • изменять содержимое открытой страницы;
  • подменять элементы интерфейса;
  • отправлять запросы от имени пользователя;
  • получать доступ к данным, доступным JavaScript;
  • читать содержимое localStorage и других доступных скрипту хранилищ;
  • наблюдать за действиями пользователя на уязвимой странице;
  • выполнять действия в веб-приложении с полномочиями текущего пользователя.

При этом важно не сводить XSS исключительно к «краже cookie». Современные браузеры используют защитные механизмы вроде HttpOnly, SameSite и других ограничений. Кроме того, вредоносный скрипт может использовать уже открытую сессию пользователя для выполнения разрешённых ему действий, даже если непосредственное содержимое cookie недоступно JavaScript. OWASP указывает среди возможных последствий XSS имперсонацию пользователя, наблюдение за его действиями и доступ к чувствительным данным.

Основные виды XSS

Традиционно выделяют три основные разновидности межсайтового скриптинга: Stored XSS, Reflected XSS и DOM-based XSS. Первые два варианта обычно связаны с обработкой данных на стороне сервера, тогда как DOM-based XSS возникает непосредственно в клиентском JavaScript при небезопасной работе с DOM. Такое разделение используется, в частности, в материалах OWASP.

Stored XSS — сохранённая XSS

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

Типичный пример — система комментариев. Посетитель отправляет комментарий, сайт сохраняет его в базе данных, а затем выводит комментарий на странице статьи. Если приложение неправильно обрабатывает пользовательский HTML, опасное содержимое может попасть в базу и впоследствии отображаться каждому посетителю соответствующей страницы.

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

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

Reflected XSS — отражённая XSS

Reflected XSS возникает, когда потенциально опасное значение поступает вместе с запросом пользователя и практически сразу возвращается сервером в HTML-ответе без необходимой обработки.

Такая ситуация может возникать, например, на страницах поиска, фильтрации или обработки параметров URL. Пользователь передаёт значение, сервер включает его в ответ, а браузер интерпретирует результат.

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

При этом сама уязвимость находится не в URL как таковом, а в неправильной обработке данных приложением. URL-параметры, значения форм, HTTP-заголовки и другие внешние данные нельзя автоматически считать безопасными.

DOM-based XSS

DOM-based XSS возникает на стороне браузера. В этом случае сервер может вообще не вернуть вредоносный код в готовом HTML. Проблема появляется в JavaScript, который получает недоверенные данные и передаёт их в небезопасный DOM API.

Например, клиентский скрипт может брать значение из URL или другого источника и помещать его непосредственно в innerHTML. В таком случае браузер может интерпретировать полученное значение как HTML.

MDN приводит DOM-ориентированный сценарий, при котором клиентский JavaScript изменяет страницу с использованием значения, контролируемого пользователем. OWASP отдельно подчёркивает, что DOM XSS отличается от серверных вариантов местом внедрения — проблема проявляется непосредственно в браузере.

Что такое DOM и почему он важен для XSS

DOM (Document Object Model) — представление HTML-документа в виде объектов, с которыми может работать JavaScript. Скрипт способен находить элементы страницы, изменять их содержимое, атрибуты и структуру.

Проблема возникает, когда недоверенные данные передаются DOM API, который интерпретирует строку как HTML или другой исполняемый контекст.

Например, принципиально различаются следующие подходы:

element.textContent = userInput;

и:

element.innerHTML = userInput;

В первом случае значение рассматривается как текст. Во втором браузер разбирает строку как HTML, поэтому при работе с недоверенными данными появляется потенциально опасный контекст.

OWASP рекомендует по возможности использовать безопасные DOM API, например textContent, вместо небезопасных способов вставки HTML.

Что такое экранирование HTML

Output encoding, или экранирование вывода, — один из основных механизмов защиты от XSS. Его задача заключается в том, чтобы данные пользователя оставались данными, а не превращались в HTML или JavaScript.

Например, специальные символы HTML могут представляться соответствующими сущностями:

  • & преобразуется в &;
  • < — в &lt;;
  • > — в &gt;;
  • " — в &quot;;
  • ' — в соответствующее безопасное HTML-представление.

После такого преобразования браузер отображает символы как обычный текст, а не интерпретирует их как элементы HTML.

Однако экранирование должно зависеть от контекста. Правила для HTML-текста отличаются от правил для HTML-атрибута, URL или JavaScript. OWASP отдельно подчёркивает необходимость контекстно-зависимого кодирования вывода.

Почему нельзя просто фильтровать опасные слова

Одна из распространённых ошибок — попытка создать список запрещённых строк и удалять их из пользовательского ввода. Такой подход называют blacklist-подходом.

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

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

Что такое HTML-санитизация

Санитизация отличается от обычного экранирования. При экранировании HTML превращается в текст. При санитизации приложение может разрешить ограниченный набор HTML-элементов и атрибутов, удаляя потенциально опасные конструкции.

Это полезно, например, в редакторах, где пользователю действительно необходимо разрешить форматирование текста с помощью определённого HTML.

Самостоятельно реализовывать сложный HTML-санитайзер обычно не стоит. Безопаснее использовать проверенные библиотеки и поддерживать их в актуальном состоянии.

OWASP рассматривает output encoding и HTML sanitization как ключевые элементы защиты и подчёркивает, что единственного универсального механизма для всех случаев XSS нет.

XSS и атрибуты HTML

Опасность существует не только при вставке данных между HTML-тегами. Отдельный класс проблем связан с HTML-атрибутами.

Например, разработчик может динамически формировать атрибут class, title, href или другой параметр. Для каждого контекста действуют свои правила безопасности.

Особенно опасны атрибуты, содержащие обработчики событий, например onclick, onerror и другие on.... Передача недоверенных данных в такие контексты может привести к выполнению JavaScript.

OWASP рекомендует помещать значения атрибутов в кавычки и использовать контекстно подходящее кодирование.

XSS в JavaScript

Отдельное внимание необходимо уделять данным, которые вставляются непосредственно в JavaScript-код. Такой контекст существенно сложнее обычного HTML.

Если значение пользователя помещается внутрь JavaScript без правильного кодирования, специальные символы могут изменить структуру выражения. Поэтому по возможности не следует конструировать JavaScript-код путём объединения его со строками, полученными от пользователя.

Вместо этого предпочтительнее передавать данные через безопасные структуры, например JSON, а затем обрабатывать их как значения, а не как фрагменты исходного кода.

XSS и URL

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

Если приложение формирует ссылку на основании внешних данных, необходимо учитывать не только HTML-экранирование, но и безопасность самого URL. Простого преобразования специальных HTML-символов в некоторых случаях недостаточно.

OWASP отдельно выделяет URL-контекст и рекомендует использовать URL-кодирование, а при помещении полного URL в HTML-атрибут дополнительно выполнять соответствующее кодирование атрибута.

Безопасные и небезопасные DOM API

В клиентском JavaScript выбор API может непосредственно влиять на риск XSS. Если приложение должно вывести строку как текст, предпочтительно использовать API, которое не интерпретирует её как HTML.

Например, для обычного текстового содержимого подходит:

element.textContent = userInput;

а для работы с HTML требуется либо гарантировать доверенность данных, либо предварительно выполнить корректную санитизацию.

OWASP приводит textContent, value, создание текстовых узлов и ряд других операций в качестве безопасных вариантов для соответствующих задач. Для случаев, когда HTML действительно необходим, должна использоваться проверенная санитизация.

Как защищать сайт от XSS

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

Основные меры защиты:

  • экранировать вывод в соответствии с контекстом;
  • санитизировать HTML, если приложение действительно разрешает пользовательскую разметку;
  • использовать безопасные DOM API;
  • валидировать данные там, где это необходимо для логики приложения;
  • не помещать недоверенные данные непосредственно в JavaScript и CSS-контексты;
  • использовать Content Security Policy как дополнительный уровень защиты;
  • при подходящей архитектуре применять Trusted Types;
  • регулярно обновлять фреймворки, библиотеки и плагины.

OWASP подчёркивает, что в современных приложениях безопасность фреймворка значительно помогает снижать риск XSS, но уязвимости всё равно могут появляться при использовании специальных механизмов, отключающих автоматическое экранирование, устаревших компонентов или небезопасных DOM API.

XSS и современные фреймворки

Современные frontend- и backend-фреймворки часто автоматически экранируют переменные при выводе в HTML. Это существенно уменьшает количество типичных XSS-ошибок.

Однако автоматическая защита не означает, что разработчик полностью освобождается от ответственности. Многие фреймворки имеют специальные механизмы для вывода «сырого» HTML, прямой работы с DOM или отключения стандартного экранирования.

Например, OWASP отдельно предупреждает о рисках использования React dangerouslySetInnerHTML, Angular-функций, отключающих стандартную защиту, и аналогичных escape hatch-механизмов в других фреймворках.

XSS в WordPress

WordPress-сайты также могут быть подвержены XSS. Источником проблемы может стать собственный код темы, плагин, обработчик AJAX, форма, комментарии, пользовательские поля или неправильный вывод данных.

Особенно важно различать функции, которые экранируют разные типы данных. Строка, предназначенная для вывода в HTML, атрибуте, URL или JavaScript, требует соответствующего способа обработки.

Типичная ошибка разработчика заключается в том, что значение из $_GET, $_POST, мета-поля или базы данных считается безопасным только потому, что оно было получено из собственного сайта. На практике данные из базы тоже могут быть недоверенными, если ранее они поступили от пользователя или были записаны уязвимым кодом.

XSS в AJAX-запросах

Использование AJAX не устраняет XSS. Напротив, клиентский JavaScript может получать данные от сервера и затем вставлять их в DOM.

Например, сервер может вернуть JSON с именем пользователя, сообщением или названием записи. Если frontend без проверки помещает полученное значение через innerHTML, уязвимость может возникнуть уже на стороне браузера.

Поэтому безопасность должна учитываться на всём пути данных: от HTTP-запроса до серверной обработки, формирования ответа и его последующего отображения JavaScript-кодом.

Content Security Policy и XSS

Content Security Policy (CSP) — механизм безопасности браузера, который позволяет задавать правила о том, какие скрипты, стили и другие ресурсы разрешено загружать и выполнять.

CSP может значительно ограничить последствия XSS, если злоумышленнику всё-таки удалось внедрить опасное содержимое. Например, политика может запрещать выполнение определённых inline-скриптов и ограничивать источники внешнего JavaScript.

Но CSP не следует рассматривать как замену правильному экранированию и санитизации. OWASP рекомендует использовать CSP как дополнительный уровень защиты, а не как единственное средство предотвращения XSS.

Trusted Types

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

Это особенно полезно для крупных JavaScript-приложений, где полностью проверить многочисленные места использования innerHTML, outerHTML, document.write и других чувствительных API бывает сложно.

OWASP рекомендует рассматривать Trusted Types как дополнительный механизм защиты, особенно для Chromium-браузеров и приложений с большим количеством клиентского кода.

Защищают ли HttpOnly и SameSite от XSS

Атрибут HttpOnly запрещает JavaScript напрямую читать соответствующую cookie. Это полезно для ограничения последствий некоторых атак, но само по себе не устраняет XSS.

Если вредоносный JavaScript выполняется в контексте сайта, он всё ещё может взаимодействовать со страницей и отправлять HTTP-запросы с полномочиями текущего пользователя в пределах доступных браузеру возможностей.

Аналогично, SameSite предназначен прежде всего для контроля отправки cookies в контексте межсайтовых запросов и не является полноценной защитой от XSS.

Поэтому cookie-флаги следует рассматривать как дополнительные меры защиты, а не как замену безопасному выводу данных.

Как обнаружить XSS

Поиск XSS начинается с анализа потоков данных. Необходимо определить, откуда приложение получает данные, где они сохраняются, как проходят через серверную обработку и где попадают в HTML или DOM.

Особое внимание следует уделять:

  • формам и полям пользовательского ввода;
  • URL-параметрам и значениям фрагмента;
  • комментариям и отзывам;
  • поисковым запросам;
  • профилям пользователей;
  • AJAX-ответам;
  • динамически создаваемому HTML;
  • местам использования innerHTML и аналогичных API.

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

XSS и валидация данных

Валидация входных данных полезна, но её не следует путать с защитой от XSS. Например, поле возраста можно ограничить целым числом, а поле телефона — определённым форматом. Такие ограничения уменьшают поверхность атаки.

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

Поэтому практический подход заключается в сочетании валидации, контекстного экранирования, санитизации там, где разрешён HTML, и безопасной работы с DOM.

Почему XSS нельзя полностью решить одним фильтром

XSS возникает на границе между данными и исполняемым кодом. Современные веб-приложения используют HTML, CSS, JavaScript, URL, JSON, DOM API и множество сторонних библиотек. Для каждого контекста существуют собственные правила обработки.

Именно поэтому универсальная функция «очистить строку от XSS» не является надёжной архитектурой. Если строка должна отображаться как текст, её необходимо вывести как текст. Если разрешён ограниченный HTML, требуется HTML-санитизация. Если значение используется в URL, необходима проверка и URL-кодирование. Если данные передаются в JavaScript, следует избегать конструирования кода из строк.

Выводы

XSS — это уязвимость веб-приложения, при которой недоверенные данные в результате неправильной обработки становятся исполняемым содержимым страницы. Проблема может возникнуть как на сервере, так и непосредственно в браузере при небезопасной работе JavaScript с DOM.

Основные разновидности XSS — Stored, Reflected и DOM-based. Stored XSS связана с сохранением опасных данных, Reflected XSS — с отражением данных из запроса в ответе, а DOM-based XSS возникает при небезопасной обработке данных клиентским кодом.

Главным способом защиты является корректное обращение с недоверенными данными. Необходимо использовать контекстное экранирование, санитизацию HTML там, где она действительно требуется, безопасные DOM API и современные механизмы защиты браузера. CSP и Trusted Types могут дополнительно снизить риск и последствия XSS, но не должны заменять правильную обработку данных.

Особенно важно помнить, что данные нельзя считать безопасными только потому, что они поступили из собственной базы данных, AJAX-ответа или CMS. Если исходно они могли быть сформированы пользователем, безопасность должна сохраняться на всём пути от ввода до отображения.

FAQ — часто задаваемые вопросы

Что такое XSS простыми словами?

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

Что означает XSS?

XSS расшифровывается как Cross-Site Scripting — «межсайтовый скриптинг».

Чем опасна XSS-атака?

В зависимости от приложения XSS может позволить изменять страницу, выполнять действия от имени пользователя, получать доступ к данным, доступным JavaScript, и использовать полномочия текущей пользовательской сессии.

Какие бывают виды XSS?

Основными категориями являются Stored XSS, Reflected XSS и DOM-based XSS. Первые две обычно связаны с серверной обработкой данных, а DOM-based XSS возникает непосредственно в клиентском коде.

Что такое Stored XSS?

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

Что такое Reflected XSS?

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

Что такое DOM XSS?

DOM XSS возникает на стороне браузера, когда клиентский JavaScript получает недоверенные данные и передаёт их в небезопасный DOM API или другой исполняемый контекст.

Защищает ли экранирование от XSS?

Правильное контекстное экранирование является одним из основных средств защиты. Однако оно должно соответствовать месту вывода данных: HTML, атрибуту, URL и JavaScript-контексту требуются разные подходы.

Помогает ли CSP против XSS?

Да, правильно настроенная Content Security Policy может ограничить выполнение внедрённого кода и служить дополнительным уровнем защиты. Однако CSP не должна заменять безопасное экранирование и санитизацию.

Защищает ли HttpOnly cookie от XSS?

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

Можно ли полностью защититься от XSS с помощью фильтра?

Надёжная защита не сводится к одному фильтру. Необходимо сочетать валидацию, контекстное экранирование, санитизацию HTML при необходимости и безопасную работу с DOM.

Опасен ли innerHTML?

Сам по себе innerHTML не является уязвимостью, но его использование с недоверенными данными создаёт опасный HTML-контекст. Для вывода обычного текста предпочтительнее использовать textContent или другие безопасные API.

Бывает ли XSS в WordPress?

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

Можно ли обнаружить XSS автоматически?

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

Дополнительная информация:

  • OWASP — Cross Site Scripting Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
  • OWASP — DOM Based XSS Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html
  • OWASP — Content Security Policy Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html
  • MDN — Cross-site scripting (XSS): https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/XSS
  • MDN — Cross-site scripting, справочник: https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting
  • OWASP — Cross Site Scripting (XSS): https://owasp.org/www-community/attacks/xss/
Уязвимость Ninja Forms активно используют для взлома WordPress-сайтов

Уязвимость Ninja Forms активно используют для взлома WordPress-сайтов

Популярный плагин Ninja Forms для WordPress снова оказался в центре внимания специалистов по информационной безопасности. В течение 2026 года для этого продукта были обнаружены несколько серьёзных уязвимостей, а некоторые из них уже используются злоумышленниками в реальных атаках. Проблемы затрагивают как основной плагин, так и отдельное дополнение Ninja Forms File Uploads.Наиболее опасной стала уязвимость CVE-2026-0740 в
Распространенные серверные эксплойты и способы защиты от них

Распространенные серверные эксплойты и способы защиты от них

Если вы управляете сервером — будь то веб-хостинг, работающее приложение или что-то скрытое от глаз — безопасность всегда должна быть в приоритете. Серверы часто становятся мишенью для кибератак, и достаточно небольшой уязвимости, чтобы она превратилась в серьёзную проблему.Хорошая новость? Большинство распространенных уязвимостей имеют хорошо известные способы устранения. В этой статье мы рассмотрим некоторые из наиболее
WordPress 5.8.1 выпущен для исправления множества уязвимостей

WordPress 5.8.1 выпущен для исправления множества уязвимостей

В обновлении WordPress 5.8.1 устранены три проблемы безопасности в REST API, редакторе Gutenberg и библиотеке Lodash JavaScript.WordPress анонсировал выпуск безопасности и обслуживания версии 5.8.1. Важно обновить WordPress, особенно версии с 5.4 по 5.8, чтобы исправить три проблемы с безопасностью. WordPress версии 5.8.1 для обеспечения безопасности и обслуживанияДля WordPress или любого другого программного обеспечения в этом отношении не
Прокрутить страницу до начала