
💡 Міжсайтовий скриптинг (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-файлу з вбудованим скриптом, введення в поле «ім'я користувача» під час реєстрації, параметри 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-атак

Класифікація 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 або будь-яке інше контрольоване джерело на клієнті. Серверні логи чисті, атаку видно лише в браузері. Виявити такий XSS найскладніше, тому що WAF і серверні сканери його не бачать.
Чому XSS особливо небезпечний для WordPress
WordPress, ціль номер один для XSS з однієї причини: екосистема. З понад 60 000 плагінів у репозиторії далеко не всі проходять суворе рецензування на екранування виводу. Один плагін з уразливістю компрометує весь сайт.
У вересні 2025 року Microsoft опублікувала розбір того, чому XSS залишається загрозою через 25 років після появи. Ключовий висновок: складність сучасного вебстеку робить повне усунення XSS майже неможливим, занадто багато шарів, де може бути пропущене екранування.
Що отримує зловмисник через XSS на WordPress:
- Доступ до адмінпанелі через викрадення сесійних cookies адміністратора
- Впровадження прихованих посилань (SEO-спам)
- Завантаження шкідливого ПЗ на комп’ютер відвідувача
- Підміну платіжних реквізитів у WooCommerce
- Масовий дефейс сторінок сайту
У поєднанні з соціальною інженерією XSS перетворюється на вектор для складних атак: від встановлення кейлогерів до підробки міжсайтових запитів.
Як захистити сайт від XSS: три шари

Захист від XSS не вирішується одним налаштуванням. Працює лише ешелонована оборона: плагіни безпеки перекривають грубі атаки, екранування виводу закриває технічні вектори, а Content Security Policy блокує виконання скриптів на рівні браузера.
Шар 1: плагіни безпеки та брандмауер
Перший рубіж, WordPress-плагін із Web Application Firewall. WAF фільтрує вхідні запити до того, як вони досягнуть коду плагінів, і блокує відомі сигнатури XSS-атак.
Вибираючи плагін безпеки, орієнтуйтеся на такий чек-лист:
- Регулярне сканування на шкідливе ПЗ та відомі CVE у встановлених плагінах
- Брандмауер із правилами для блокування XSS-патернів у запитах
- Харденінг WordPress: вимкнення XML-RPC, зміна префікса таблиць, заборона редагування файлів з адмінки
- Централізоване керування оновленнями всіх плагінів і тем
- Резервне копіювання, щоб відновити сайт, якщо атака все ж пройшла
Добірку плагінів безпеки WordPress з детальним розбором функцій кожного інструмента шукайте в профільних оглядах на нашому сайті.
Шар 2: валідація та екранування виводу
Це головний технічний рубіж. Правило просте й не обговорюється: жодні користувацькі дані не виводяться в браузер без екранування. WordPress надає для цього вбудовані функції, і кожна прив'язана до конкретного контексту виводу.
Базовий арсенал розробника WordPress:
1 // Для вывода внутри HTML-тегов — между <p> и </p> 2 echo esc_html($user_input); 3 4 // Для атрибутов HTML — внутри value="..." 5 echo esc_attr($user_input); 6 7 // Для URL в href, src и других атрибутах 8 echo esc_url($user_url); 9 10 // Для вывода текста внутри <textarea> 11 echo esc_textarea($user_text); 12 13 // Для JavaScript-переменных 14 echo esc_js($user_data); 15 16 // Для разрешенных HTML-тегов с удалением опасных атрибутов 17 echo 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 или через плагин 2 function 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 } 5 add_action('send_headers', 'add_csp_header');
Сувора політика ('strict-dynamic' замість 'unsafe-inline') безпечніша, але потребує налаштування nonce або хешів для кожного легітимного скрипта — це об'ємна робота на сайті з десятком активних плагінів. Почніть із report-only режиму, щоб зібрати логи порушень і не зламати фронтенд:
1 Content-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.



