Skip to content

Всё для WordPress, веб-разработки — и не только

💡 Межсайтовый скриптинг (XSS): что это и как защитить сайт в 2026

💡 Межсайтовый скриптинг (XSS): что это и как защитить сайт в 2026

В 2019 почти 75% крупных компаний столкнулись с межсайтовым скриптингом. Спустя семь лет XSS никуда не делся. Microsoft отчиталась о 970 случаях XSS, закрытых только с января 2024, а одна уязвимость 2025 года в плагине LiteSpeed Cache поставила под удар 7 миллионов сайтов на WordPress.

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

Разберем механику XSS, три типа атак и конкретные слои защиты, которые закрывают сайт от межсайтового скриптинга. С инструментами, примерами кода и реальными кейсами WordPress.

💡 Быстрый обзор:

  • Что такое XSS и как злоумышленник внедряет вредоносный код на доверенный сайт
  • Три типа межсайтового скриптинга, хранимый, отраженный и DOM-based, и чем они отличаются
  • Пошаговая настройка трех слоев защиты: WAF, экранирование вывода и Content Security Policy
  • Где искать XSS-уязвимости на своем сайте и что делать, если атака уже произошла

Что такое межсайтовый скриптинг

Схема атаки межсайтового скриптинга на веб-сайт

Cross-Site Scripting, это инъекционная атака, при которой злоумышленник внедряет вредоносный скрипт в страницу доверенного сайта. Браузер жертвы выполняет этот код, потому что воспринимает его как часть легитимной страницы. Отсюда и название: скрипт приходит «с crossing site boundary», с пересечением границы сайта.

Технически вектор атаки не ограничивается JavaScript. Уязвимости возможны в HTML, Flash, ActiveX и CSS. Но на практике подавляющее большинство эксплойтов целятся именно в JS. Причина, доступ к DOM-дереву, cookies, localStorage и возможность выполнять запросы от имени пользователя.

В WordPress уязвимость почти всегда возникает через плагины и темы, которые неправильно обрабатывают пользовательский ввод. Формы комментариев, поисковые строки, контактные формы, страницы логина, любое поле, которое принимает данные и выводит их обратно без фильтрации, становится точкой входа. По данным компании Claranet, в 2024 году нашли 2570 случаев отраженного и хранимого XSS в проверенных веб-приложениях.

Как работает XSS

Злоумышленнику нужны два условия: точка входа для вредоносного кода и отсутствие фильтрации на выходе. На практике это реализуется двумя путями, через манипуляцию пользовательским вводом и через обход same-origin policy.

Внедрение через пользовательский ввод

Самый распространенный сценарий. Пользовательское поле, строка поиска, форма комментария, поле загрузки файла, принимает не только текст, но и исполняемый код. Если плагин или тема не экранируют вывод, введенный <script>alert('XSS')</script> выполнится в браузере каждого, кто откроет страницу.

Проблема глубже, чем кажется. Даже опытные разработчики пропускают векторы XSS через, казалось бы, безобидные поля: загрузка SVG-файла с embedded-скриптом, ввод в поле «имя пользователя» при регистрации, параметры URL в редиректах. Одно поле без esc_url() или esc_attr(), и сайт открыт.

В идеальном мире поле поиска принимает простой текст и ничего больше. В реальном WordPress экосистема из 60 000+ плагинов делает эту гарантию недостижимой, достаточно одного плагина с echo $_GET['q'] без esc_html().

Обход same-origin policy

Иллюстрация обхода политики одинакового происхождения браузера

Same-origin policy, фундаментальное правило безопасности браузеров: скрипты с одного источника не могут читать данные с другого. Страница Facebook и страница банка, открытые в одном браузере, не обмениваются информацией. Но у этого правила есть ахиллесова пята, сессионные cookies.

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

Схема атаки: злоумышленник находит XSS-уязвимость на сайте example.com → внедряет скрипт, который читает document.cookie → отправляет сессионную cookie на свой сервер. Итог: полный доступ к аккаунту жертвы без знания пароля. Cookie сессии хранят учетные данные, содержимое корзины, информацию о доставке, весь контекст пользователя.

Три типа XSS-атак

Скриншот обучающей игры Google XSS Game для поиска уязвимостей

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

Хранимый XSS (Stored, тип I)

Самый опасный тип. Вредоносный скрипт сохраняется на сервере, в базе данных, в логах, в поле комментария, и выполняется при каждом открытии зараженной страницы. На WordPress это классический сценарий: злоумышленник оставляет комментарий с <script>-тегом, плагин комментариев не фильтрует HTML, и скрипт срабатывает у каждого посетителя поста.

Особенность хранимого XSS в том, что атаку не нужно активировать через фишинговую ссылку. Жертва просто заходит на страницу. В 2025 году уязвимость CVE-2025-12709 в плагине Interactions для WordPress, классический stored XSS из-за недостаточной санитизации ввода в селекторах событий.

Отраженный XSS (Reflected, тип II)

Злоумышленник отправляет жертве ссылку, содержащую вредоносный код в параметрах URL. Сервер «отражает» этот код обратно в ответе, например, в сообщении об ошибке поиска или в строке «Вы искали: X». Браузер выполняет скрипт, потому что он пришел в теле ответа от доверенного сервера.

Отраженный XSS требует активного действия жертвы, клика по ссылке. Поэтому атаку часто маскируют под легитимный URL в фишинговом письме. На WordPress типичный вектор, поисковые плагины, которые выводят поисковый запрос без esc_html().

DOM-based XSS (тип 0)

В отличие от первых двух, здесь уязвимость находится не в серверном коде, а в клиентском JavaScript. Вредоносные данные никогда не уходят на сервер, они обрабатываются прямо в браузере через небезопасные методы DOM-API, такие как innerHTML, document.write() или eval().

Источником данных служит URL (через window.location), document.referrer или любой другой controllable-источник на клиенте. Серверные логи чисты, атаку видно только в браузере. Обнаружить такой XSS сложнее всего, потому что WAF и серверные сканеры его не видят.

Почему XSS особенно опасен для WordPress

WordPress, цель номер один для XSS по одной причине: экосистема. Из 60 000+ плагинов в репозитории далеко не все проходят строгий ревью на экранирование вывода. Один плагин с уязвимостью компрометирует весь сайт.

В сентябре 2025 года Microsoft опубликовала разбор того, почему XSS остается угрозой спустя 25 лет после появления. Ключевой вывод: сложность modern web stack делает полное устранение XSS почти невозможным, слишком много слоев, где может быть пропущено экранирование.

Что получает злоумышленник через XSS на WordPress:

  • Доступ к админ-панели через кражу сессионных cookies администратора
  • Внедрение скрытых ссылок (SEO-спам)
  • Загрузку вредоносного ПО на компьютер посетителя
  • Подмену платежных реквизитов в WooCommerce
  • Массовый дефейс страниц сайта

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

Как защитить сайт от XSS: три слоя

Три слоя защиты WordPress от межсайтового скриптинга

Защита от XSS не решается одной настройкой. Работает только эшелонированная оборона: плагины безопасности перекрывают грубые атаки, экранирование вывода закрывает технические векторы, а Content Security Policy блокирует выполнение скриптов на уровне браузера.

Слой 1: плагины безопасности и брандмауэр

Первый рубеж, WordPress-плагин с Web Application Firewall. WAF фильтрует входящие запросы до того, как они достигнут кода плагинов, и блокирует известные сигнатуры XSS-атак.

При выборе плагина безопасности ориентируйтесь на такой чек-лист:

  • Регулярное сканирование на вредоносное ПО и известные CVE в установленных плагинах
  • Брандмауэр с правилами для блокировки XSS-паттернов в запросах
  • Харденинг WordPress: отключение XML-RPC, смена префикса таблиц, запрет редактирования файлов из админки
  • Централизованное управление обновлениями всех плагинов и тем
  • Резервное копирование, чтобы восстановить сайт, если атака все же прошла

Подборку плагинов безопасности WordPress с детальным разбором функций каждого инструмента ищите в профильных обзорах на нашем сайте.

Слой 2: валидация и экранирование вывода

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

Базовый арсенал разработчика WordPress:

1// Для вывода внутри HTML-тегов — между <p> и </p>
2echo esc_html($user_input);
3
4// Для атрибутов HTML — внутри value="..."
5echo esc_attr($user_input);
6
7// Для URL в href, src и других атрибутах
8echo esc_url($user_url);
9
10// Для вывода текста внутри <textarea>
11echo esc_textarea($user_text);
12
13// Для JavaScript-переменных
14echo esc_js($user_data);
15
16// Для разрешенных HTML-тегов с удалением опасных атрибутов
17echo wp_kses_post($user_html);

Ключевой момент: выбор функции зависит от контекста. esc_html() в атрибуте href не спасет, злоумышленник вставит javascript:alert('XSS'). И наоборот, esc_url() внутри параграфа пропустит <script>-тег. Контекст определяет функцию.

Отдельно стоит wp_kses(), мощный фильтр, который пропускает только разрешенные HTML-теги и атрибуты. Для пользовательского контента (комментарии, описания профилей, пользовательские поля) это минимально необходимый уровень фильтрации.

Слой 3: Content Security Policy (CSP)

CSP, HTTP-заголовок, который говорит браузеру: «Выполняй скрипты только с этих источников». Это последний рубеж. Даже если злоумышленник внедрил <script> в страницу, браузер его не выполнит, потому что инлайн-скрипты не входят в белый список.

Базовая CSP-политика для WordPress:

1// В functions.php или через плагин
2function add_csp_header() {
3 header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;");
4}
5add_action('send_headers', 'add_csp_header');

Строгая политика ('strict-dynamic' вместо 'unsafe-inline') безопаснее, но требует настройки nonce или хешей для каждого легитимного скрипта, это объемная работа на сайте с десятком активных плагинов. Начните с report-only режима, чтобы собрать логи нарушений и не сломать фронтенд:

1Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report-endpoint

CSP не заменяет экранирование. Он смягчает последствия ошибки, когда экранирование где-то пропустили.

Видео: XSS от азов до эксплуатации

Чтобы увидеть XSS в действии и понять, как искать уязвимости на реальных сайтах, посмотрите этот 30-минутный разбор:

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

⁉️🤔 Частые вопросы

Поможет ли обновление WordPress и плагинов защитить от XSS?

Да, и это самый недооцененный шаг защиты. Каждая новая версия плагина часто закрывает конкретные CVE, в том числе XSS-уязвимости. Уязвимость LiteSpeed Cache CVE-2025-12450 была закрыта патчем в течение недели после обнаружения, но 7 миллионов сайтов, которые не обновились, остались открыты. Включите автообновление для всех плагинов, потеря совместимости случается редко, а пропущенный патч бьет гарантированно.

Достаточно ли одного плагина безопасности для защиты от XSS?

Нет. Плагин безопасности с WAF закрывает известные сигнатуры атак, но не видит zero-day уязвимости и нестандартные векторы. Он должен быть первым слоем, за которым идут экранирование вывода в коде темы и CSP-заголовки. Три слоя вместе дают защиту, которую не обеспечит ни один из них по отдельности.

Как проверить, есть ли на моем сайте XSS-уязвимости?

Начните с бесплатного сканера, WPScan, Sucuri SiteCheck, Qualys SSL Labs. Для более глубокой проверки запустите OWASP ZAP (Zed Attack Proxy), open-source инструмент, который автоматически фаззит поля ввода и ловит отраженный XSS. Важно: автоматические сканеры не видят DOM-based XSS, для него нужен ручной аудит JavaScript-кода сайта.

Можно ли полностью исключить XSS на большом сайте?

Полное исключение XSS на сайте с десятками плагинов и кастомной темой, задача, близкая к идеалу, но трудно достижимая полностью. Каждый новый плагин, каждое обновление темы, каждый кастомный сниппет в functions.php, потенциальная точка входа. Реалистичная цель: три слоя защиты, автообновления, ежеквартальный аудит и CSP в report-only режиме. Так вы отловите подавляющее большинство атак на ранней стадии.

Что делать, если сайт уже атакован через XSS?

Немедленно смените все пароли и сбросьте сессионные ключи в wp-config.php через генератор WordPress. Затем восстановите сайт из чистой резервной копии. После восстановления установите плагин безопасности, обновите все плагины и темы до последних версий, добавьте CSP-заголовок в functions.php. Менять пароли нужно, потому что XSS часто крадет сессионные cookies администратора.

XSS и SQL-инъекция, это одно и то же?

Нет, хотя обе относятся к injection-атакам. SQL-инъекция бьет в базу данных через SQL-запрос, злоумышленник может прочитать, изменить или удалить таблицы. XSS бьет в браузер пользователя через JavaScript, цель украсть сессию, показать фишинговую форму, подменить контент страницы. У них разные векторы, разные функции защиты ($wpdb->prepare() для SQL, esc_html() для XSS) и разные последствия. Но на практике они часто идут в связке: XSS используют для доставки SQL-инъекции через админ-панель.

Стоит ли бояться XSS в 2026

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

Если вы прямо сейчас не используете ни одного из этих слоев, начните с установки плагина безопасности и включения автообновлений в админке WordPress. Это займет 10 минут и закроет самые грубые входы. А потом возвращайтесь к этой статье, когда будете готовы внедрить экранирование и CSP.